HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifference, -1, -1, 2, {INS_sabd, INS_uabd, INS_sabd, INS_uabd, INS_sabd, INS_uabd, INS_invalid, INS_invalid, INS_fabd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, Add, -1, -1, 2, {INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_fadd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_Commutative|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, AddScalar, -1, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_add, INS_add, INS_fadd, INS_fadd}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd, And, -1, -1, 2, {INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd, BitwiseClear, -1, -1, 2, {INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, BitwiseSelect, -1, -1, 3, {INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize|HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_Commutative|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, CompareLessThan, -1, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize|HW_Flag_SpecialCodeGen)
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, LeadingSignCount, -1, -1, 1, {INS_cls, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, LeadingZeroCount, -1, -1, 1, {INS_clz, INS_clz, INS_clz, INS_clz, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, LoadVector64, -1, 8, 1, {INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(AdvSimd, LoadVector128, -1, 16, 1, {INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(AdvSimd, Max, -1, -1, 2, {INS_smax, INS_umax, INS_smax, INS_umax, INS_smax, INS_umax, INS_invalid, INS_invalid, INS_fmax, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd, Min, -1, -1, 2, {INS_smin, INS_umin, INS_smin, INS_umin, INS_smin, INS_umin, INS_invalid, INS_invalid, INS_fmin, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd, Multiply, -1, -1, 2, {INS_mul, INS_mul, INS_mul, INS_mul, INS_mul, INS_mul, INS_invalid, INS_invalid, INS_fmul, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd, MultiplyScalar, -1, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul, INS_fmul}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd, Negate, -1, -1, 1, {INS_neg, INS_invalid, INS_neg, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_invalid, INS_fneg, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
+HARDWARE_INTRINSIC(AdvSimd, NegateScalar, -1, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fneg, INS_fneg}, HW_Category_SIMDScalar, HW_Flag_NoContainment)
+HARDWARE_INTRINSIC(AdvSimd, Not, -1, -1, 1, {INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
+HARDWARE_INTRINSIC(AdvSimd, Or, -1, -1, 2, {INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd, OrNot, -1, -1, 2, {INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, PopCount, -1, -1, 1, {INS_cnt, INS_cnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
+HARDWARE_INTRINSIC(AdvSimd, SqrtScalar, -1, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fsqrt, INS_fsqrt}, HW_Category_SIMDScalar, HW_Flag_NoContainment)
+HARDWARE_INTRINSIC(AdvSimd, Subtract, -1, -1, 2, {INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_fsub, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
+HARDWARE_INTRINSIC(AdvSimd, SubtractScalar, -1, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sub, INS_sub, INS_fsub, INS_fsub}, HW_Category_SIMDScalar, HW_Flag_NoContainment)
+HARDWARE_INTRINSIC(AdvSimd, Xor, -1, -1, 2, {INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize|HW_Flag_Commutative)
// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// ISA Function name ival SIMD size NumArg instructions Category Flags
HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqualScalar, -1, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareTest, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmtst, INS_cmtst, INS_invalid, INS_cmtst}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_Commutative)
HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareTestScalar, -1, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmtst, INS_cmtst, INS_invalid, INS_cmtst}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, Divide, -1, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fdiv, INS_fdiv}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, Max, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmax}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxScalar, -1, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmax, INS_fmax}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, Min, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmin}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, MinScalar, -1, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmin, INS_fmin}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, Multiply, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, Negate, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_fneg}, HW_Category_SimpleSIMD, HW_Flag_NoContainment)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, NegateScalar, -1, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoContainment)
HARDWARE_INTRINSIC(AdvSimd_Arm64, ReverseElementBits, -1, -1, 1, {INS_rbit, INS_rbit, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, Sqrt, -1, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fsqrt, INS_fsqrt}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, Subtract, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fsub}, HW_Category_SimpleSIMD, HW_Flag_NoContainment)
HARDWARE_INTRINSIC(AdvSimd_Arm64, TransposeEven, -1, -1, 2, {INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd_Arm64, TransposeOdd, -1, -1, 2, {INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd_Arm64, UnzipEven, -1, -1, 2, {INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
<Compile Include="CompareTestScalar.Vector64.Double.cs" />
<Compile Include="CompareTestScalar.Vector64.Int64.cs" />
<Compile Include="CompareTestScalar.Vector64.UInt64.cs" />
+ <Compile Include="Divide.Vector64.Single.cs" />
+ <Compile Include="Divide.Vector128.Double.cs" />
+ <Compile Include="Divide.Vector128.Single.cs" />
+ <Compile Include="Max.Vector128.Double.cs" />
+ <Compile Include="MaxScalar.Vector64.Double.cs" />
+ <Compile Include="MaxScalar.Vector64.Single.cs" />
+ <Compile Include="Min.Vector128.Double.cs" />
+ <Compile Include="MinScalar.Vector64.Double.cs" />
+ <Compile Include="MinScalar.Vector64.Single.cs" />
+ <Compile Include="Multiply.Vector128.Double.cs" />
+ <Compile Include="Negate.Vector128.Double.cs" />
+ <Compile Include="Negate.Vector128.Int64.cs" />
+ <Compile Include="NegateScalar.Vector64.Int64.cs" />
<Compile Include="ReverseElementBits.Vector128.Byte.cs" />
<Compile Include="ReverseElementBits.Vector128.SByte.cs" />
<Compile Include="ReverseElementBits.Vector64.Byte.cs" />
<Compile Include="ReverseElementBits.Vector64.SByte.cs" />
+ <Compile Include="Sqrt.Vector64.Single.cs" />
+ <Compile Include="Sqrt.Vector128.Double.cs" />
+ <Compile Include="Sqrt.Vector128.Single.cs" />
+ <Compile Include="Subtract.Vector128.Double.cs" />
<Compile Include="TransposeEven.Vector64.Byte.cs" />
<Compile Include="TransposeEven.Vector64.Int16.cs" />
<Compile Include="TransposeEven.Vector64.Int32.cs" />
<Compile Include="CompareTestScalar.Vector64.Double.cs" />
<Compile Include="CompareTestScalar.Vector64.Int64.cs" />
<Compile Include="CompareTestScalar.Vector64.UInt64.cs" />
+ <Compile Include="Divide.Vector64.Single.cs" />
+ <Compile Include="Divide.Vector128.Double.cs" />
+ <Compile Include="Divide.Vector128.Single.cs" />
+ <Compile Include="Max.Vector128.Double.cs" />
+ <Compile Include="MaxScalar.Vector64.Double.cs" />
+ <Compile Include="MaxScalar.Vector64.Single.cs" />
+ <Compile Include="Min.Vector128.Double.cs" />
+ <Compile Include="MinScalar.Vector64.Double.cs" />
+ <Compile Include="MinScalar.Vector64.Single.cs" />
+ <Compile Include="Multiply.Vector128.Double.cs" />
+ <Compile Include="Negate.Vector128.Double.cs" />
+ <Compile Include="Negate.Vector128.Int64.cs" />
+ <Compile Include="NegateScalar.Vector64.Int64.cs" />
<Compile Include="ReverseElementBits.Vector128.Byte.cs" />
<Compile Include="ReverseElementBits.Vector128.SByte.cs" />
<Compile Include="ReverseElementBits.Vector64.Byte.cs" />
<Compile Include="ReverseElementBits.Vector64.SByte.cs" />
+ <Compile Include="Sqrt.Vector64.Single.cs" />
+ <Compile Include="Sqrt.Vector128.Double.cs" />
+ <Compile Include="Sqrt.Vector128.Single.cs" />
+ <Compile Include="Subtract.Vector128.Double.cs" />
<Compile Include="TransposeEven.Vector64.Byte.cs" />
<Compile Include="TransposeEven.Vector64.Int16.cs" />
<Compile Include="TransposeEven.Vector64.Int32.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 Divide_Vector128_Double()
+ {
+ var test = new SimpleBinaryOpTest__Divide_Vector128_Double();
+
+ 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__Divide_Vector128_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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 Vector128<Double> _fld1;
+ public Vector128<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Divide_Vector128_Double testClass)
+ {
+ var result = AdvSimd.Arm64.Divide(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Divide_Vector128_Double testClass)
+ {
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Divide(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+ private static Vector128<Double> _clsVar2;
+
+ private Vector128<Double> _fld1;
+ private Vector128<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Divide_Vector128_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ }
+
+ public SimpleBinaryOpTest__Divide_Vector128_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.Divide(
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_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.Arm64.Divide(
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.Divide), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.Divide), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.Divide(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Arm64.Divide(
+ AdvSimd.LoadVector128((Double*)(pClsVar1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Arm64.Divide(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.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Arm64.Divide(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Divide_Vector128_Double();
+ var result = AdvSimd.Arm64.Divide(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__Divide_Vector128_Double();
+
+ fixed (Vector128<Double>* pFld1 = &test._fld1)
+ fixed (Vector128<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Arm64.Divide(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.Divide(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Divide(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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.Arm64.Divide(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.Arm64.Divide(
+ AdvSimd.LoadVector128((Double*)(&test._fld1)),
+ AdvSimd.LoadVector128((Double*)(&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(Vector128<Double> op1, Vector128<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.Divide(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.Divide)}<Double>(Vector128<Double>, Vector128<Double>): {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 Divide_Vector128_Single()
+ {
+ var test = new SimpleBinaryOpTest__Divide_Vector128_Single();
+
+ 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__Divide_Vector128_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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 Vector128<Single> _fld1;
+ public Vector128<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Divide_Vector128_Single testClass)
+ {
+ var result = AdvSimd.Arm64.Divide(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Divide_Vector128_Single testClass)
+ {
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Divide(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Divide_Vector128_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Divide_Vector128_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.Divide(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_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.Arm64.Divide(
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.Divide), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.Divide), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.Divide(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Arm64.Divide(
+ AdvSimd.LoadVector128((Single*)(pClsVar1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Arm64.Divide(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.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Arm64.Divide(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Divide_Vector128_Single();
+ var result = AdvSimd.Arm64.Divide(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__Divide_Vector128_Single();
+
+ fixed (Vector128<Single>* pFld1 = &test._fld1)
+ fixed (Vector128<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Arm64.Divide(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.Divide(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Divide(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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.Arm64.Divide(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.Arm64.Divide(
+ AdvSimd.LoadVector128((Single*)(&test._fld1)),
+ AdvSimd.LoadVector128((Single*)(&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(Vector128<Single> op1, Vector128<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Divide(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.Divide)}<Single>(Vector128<Single>, Vector128<Single>): {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 Divide_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__Divide_Vector64_Single();
+
+ 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__Divide_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Divide_Vector64_Single testClass)
+ {
+ var result = AdvSimd.Arm64.Divide(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Divide_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Divide(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Divide_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Divide_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.Divide(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.Arm64.Divide(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.Divide), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.Divide), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.Divide(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Arm64.Divide(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Arm64.Divide(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Arm64.Divide(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Divide_Vector64_Single();
+ var result = AdvSimd.Arm64.Divide(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__Divide_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Arm64.Divide(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.Divide(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Divide(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.Arm64.Divide(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.Arm64.Divide(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Divide(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.Divide)}<Single>(Vector64<Single>, Vector64<Single>): {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 Max_Vector128_Double()
+ {
+ var test = new SimpleBinaryOpTest__Max_Vector128_Double();
+
+ 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__Max_Vector128_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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 Vector128<Double> _fld1;
+ public Vector128<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Max_Vector128_Double testClass)
+ {
+ var result = AdvSimd.Arm64.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector128_Double testClass)
+ {
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Max(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+ private static Vector128<Double> _clsVar2;
+
+ private Vector128<Double> _fld1;
+ private Vector128<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_Vector128_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ }
+
+ public SimpleBinaryOpTest__Max_Vector128_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.Max(
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_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.Arm64.Max(
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.Max), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.Max), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.Max(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Arm64.Max(
+ AdvSimd.LoadVector128((Double*)(pClsVar1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Arm64.Max(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.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Arm64.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector128_Double();
+ var result = AdvSimd.Arm64.Max(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__Max_Vector128_Double();
+
+ fixed (Vector128<Double>* pFld1 = &test._fld1)
+ fixed (Vector128<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Arm64.Max(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.Max(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Max(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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.Arm64.Max(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.Arm64.Max(
+ AdvSimd.LoadVector128((Double*)(&test._fld1)),
+ AdvSimd.LoadVector128((Double*)(&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(Vector128<Double> op1, Vector128<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.Max(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.Max)}<Double>(Vector128<Double>, Vector128<Double>): {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 MaxScalar_Vector64_Double()
+ {
+ var test = new SimpleBinaryOpTest__MaxScalar_Vector64_Double();
+
+ 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__MaxScalar_Vector64_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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<Double> _fld1;
+ public Vector64<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__MaxScalar_Vector64_Double testClass)
+ {
+ var result = AdvSimd.Arm64.MaxScalar(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__MaxScalar_Vector64_Double testClass)
+ {
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.MaxScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector64<Double> _clsVar1;
+ private static Vector64<Double> _clsVar2;
+
+ private Vector64<Double> _fld1;
+ private Vector64<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__MaxScalar_Vector64_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ }
+
+ public SimpleBinaryOpTest__MaxScalar_Vector64_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.MaxScalar(
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_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.Arm64.MaxScalar(
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.MaxScalar), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.MaxScalar), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.MaxScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Arm64.MaxScalar(
+ AdvSimd.LoadVector64((Double*)(pClsVar1)),
+ AdvSimd.LoadVector64((Double*)(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<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Arm64.MaxScalar(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((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Arm64.MaxScalar(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__MaxScalar_Vector64_Double();
+ var result = AdvSimd.Arm64.MaxScalar(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__MaxScalar_Vector64_Double();
+
+ fixed (Vector64<Double>* pFld1 = &test._fld1)
+ fixed (Vector64<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Arm64.MaxScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.MaxScalar(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.MaxScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(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.Arm64.MaxScalar(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.Arm64.MaxScalar(
+ AdvSimd.LoadVector64((Double*)(&test._fld1)),
+ AdvSimd.LoadVector64((Double*)(&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<Double> op1, Vector64<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(Helpers.Max(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.MaxScalar)}<Double>(Vector64<Double>, Vector64<Double>): {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 MaxScalar_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__MaxScalar_Vector64_Single();
+
+ 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__MaxScalar_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__MaxScalar_Vector64_Single testClass)
+ {
+ var result = AdvSimd.Arm64.MaxScalar(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__MaxScalar_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.MaxScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__MaxScalar_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__MaxScalar_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.MaxScalar(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.Arm64.MaxScalar(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.MaxScalar), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.MaxScalar), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.MaxScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Arm64.MaxScalar(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Arm64.MaxScalar(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Arm64.MaxScalar(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__MaxScalar_Vector64_Single();
+ var result = AdvSimd.Arm64.MaxScalar(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__MaxScalar_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Arm64.MaxScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.MaxScalar(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.MaxScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.Arm64.MaxScalar(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.Arm64.MaxScalar(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(Helpers.Max(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.MaxScalar)}<Single>(Vector64<Single>, Vector64<Single>): {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 Min_Vector128_Double()
+ {
+ var test = new SimpleBinaryOpTest__Min_Vector128_Double();
+
+ 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__Min_Vector128_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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 Vector128<Double> _fld1;
+ public Vector128<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Min_Vector128_Double testClass)
+ {
+ var result = AdvSimd.Arm64.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector128_Double testClass)
+ {
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Min(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+ private static Vector128<Double> _clsVar2;
+
+ private Vector128<Double> _fld1;
+ private Vector128<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_Vector128_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ }
+
+ public SimpleBinaryOpTest__Min_Vector128_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.Min(
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_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.Arm64.Min(
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.Min), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.Min), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.Min(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Arm64.Min(
+ AdvSimd.LoadVector128((Double*)(pClsVar1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Arm64.Min(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.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Arm64.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector128_Double();
+ var result = AdvSimd.Arm64.Min(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__Min_Vector128_Double();
+
+ fixed (Vector128<Double>* pFld1 = &test._fld1)
+ fixed (Vector128<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Arm64.Min(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.Min(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Min(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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.Arm64.Min(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.Arm64.Min(
+ AdvSimd.LoadVector128((Double*)(&test._fld1)),
+ AdvSimd.LoadVector128((Double*)(&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(Vector128<Double> op1, Vector128<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.Min(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.Min)}<Double>(Vector128<Double>, Vector128<Double>): {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 MinScalar_Vector64_Double()
+ {
+ var test = new SimpleBinaryOpTest__MinScalar_Vector64_Double();
+
+ 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__MinScalar_Vector64_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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<Double> _fld1;
+ public Vector64<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__MinScalar_Vector64_Double testClass)
+ {
+ var result = AdvSimd.Arm64.MinScalar(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__MinScalar_Vector64_Double testClass)
+ {
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.MinScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector64<Double> _clsVar1;
+ private static Vector64<Double> _clsVar2;
+
+ private Vector64<Double> _fld1;
+ private Vector64<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__MinScalar_Vector64_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ }
+
+ public SimpleBinaryOpTest__MinScalar_Vector64_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.MinScalar(
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_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.Arm64.MinScalar(
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.MinScalar), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.MinScalar), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.MinScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Arm64.MinScalar(
+ AdvSimd.LoadVector64((Double*)(pClsVar1)),
+ AdvSimd.LoadVector64((Double*)(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<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Arm64.MinScalar(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((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Arm64.MinScalar(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__MinScalar_Vector64_Double();
+ var result = AdvSimd.Arm64.MinScalar(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__MinScalar_Vector64_Double();
+
+ fixed (Vector64<Double>* pFld1 = &test._fld1)
+ fixed (Vector64<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Arm64.MinScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.MinScalar(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.MinScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(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.Arm64.MinScalar(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.Arm64.MinScalar(
+ AdvSimd.LoadVector64((Double*)(&test._fld1)),
+ AdvSimd.LoadVector64((Double*)(&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<Double> op1, Vector64<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(Helpers.Min(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.MinScalar)}<Double>(Vector64<Double>, Vector64<Double>): {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 MinScalar_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__MinScalar_Vector64_Single();
+
+ 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__MinScalar_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__MinScalar_Vector64_Single testClass)
+ {
+ var result = AdvSimd.Arm64.MinScalar(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__MinScalar_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.MinScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__MinScalar_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__MinScalar_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.MinScalar(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.Arm64.MinScalar(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.MinScalar), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.MinScalar), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.MinScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Arm64.MinScalar(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Arm64.MinScalar(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Arm64.MinScalar(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__MinScalar_Vector64_Single();
+ var result = AdvSimd.Arm64.MinScalar(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__MinScalar_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Arm64.MinScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.MinScalar(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.MinScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.Arm64.MinScalar(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.Arm64.MinScalar(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(Helpers.Min(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.MinScalar)}<Single>(Vector64<Single>, Vector64<Single>): {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 Multiply_Vector128_Double()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_Vector128_Double();
+
+ 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__Multiply_Vector128_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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 Vector128<Double> _fld1;
+ public Vector128<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Multiply_Vector128_Double testClass)
+ {
+ var result = AdvSimd.Arm64.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector128_Double testClass)
+ {
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Multiply(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+ private static Vector128<Double> _clsVar2;
+
+ private Vector128<Double> _fld1;
+ private Vector128<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_Vector128_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ }
+
+ public SimpleBinaryOpTest__Multiply_Vector128_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.Multiply(
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_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.Arm64.Multiply(
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.Multiply), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.Multiply), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.Multiply(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Arm64.Multiply(
+ AdvSimd.LoadVector128((Double*)(pClsVar1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Arm64.Multiply(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.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Arm64.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector128_Double();
+ var result = AdvSimd.Arm64.Multiply(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__Multiply_Vector128_Double();
+
+ fixed (Vector128<Double>* pFld1 = &test._fld1)
+ fixed (Vector128<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Arm64.Multiply(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Multiply(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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.Arm64.Multiply(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.Arm64.Multiply(
+ AdvSimd.LoadVector128((Double*)(&test._fld1)),
+ AdvSimd.LoadVector128((Double*)(&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(Vector128<Double> op1, Vector128<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.Multiply(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.Multiply)}<Double>(Vector128<Double>, Vector128<Double>): {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 Negate_Vector128_Double()
+ {
+ var test = new SimpleUnaryOpTest__Negate_Vector128_Double();
+
+ 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__Negate_Vector128_Double
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, 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<Double> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Negate_Vector128_Double testClass)
+ {
+ var result = AdvSimd.Arm64.Negate(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Negate_Vector128_Double testClass)
+ {
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Arm64.Negate(
+ AdvSimd.LoadVector128((Double*)(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<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+
+ private Vector128<Double> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Negate_Vector128_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ }
+
+ public SimpleUnaryOpTest__Negate_Vector128_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.Negate(
+ Unsafe.Read<Vector128<Double>>(_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.Arm64.Negate(
+ AdvSimd.LoadVector128((Double*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.Negate), new Type[] { typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.Negate), new Type[] { typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.Negate(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Double>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Arm64.Negate(
+ AdvSimd.LoadVector128((Double*)(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<Double>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Arm64.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Arm64.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Negate_Vector128_Double();
+ var result = AdvSimd.Arm64.Negate(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__Negate_Vector128_Double();
+
+ fixed (Vector128<Double>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Arm64.Negate(
+ AdvSimd.LoadVector128((Double*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.Negate(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Arm64.Negate(
+ AdvSimd.LoadVector128((Double*)(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.Arm64.Negate(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.Arm64.Negate(
+ AdvSimd.LoadVector128((Double*)(&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<Double> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.Negate(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.Negate)}<Double>(Vector128<Double>): {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 Negate_Vector128_Int64()
+ {
+ var test = new SimpleUnaryOpTest__Negate_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__Negate_Vector128_Int64
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int64[] inArray1, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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__Negate_Vector128_Int64 testClass)
+ {
+ var result = AdvSimd.Arm64.Negate(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Negate_Vector128_Int64 testClass)
+ {
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Arm64.Negate(
+ 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<Vector128<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+
+ private static Vector128<Int64> _clsVar1;
+
+ private Vector128<Int64> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Negate_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__Negate_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 Int64[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.Negate(
+ 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.Arm64.Negate(
+ 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.Arm64).GetMethod(nameof(AdvSimd.Arm64.Negate), new Type[] { typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.Negate), new Type[] { typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.Negate(
+ _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.Arm64.Negate(
+ 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.Arm64.Negate(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.Arm64.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Negate_Vector128_Int64();
+ var result = AdvSimd.Arm64.Negate(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__Negate_Vector128_Int64();
+
+ fixed (Vector128<Int64>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Arm64.Negate(
+ 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.Arm64.Negate(_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.Arm64.Negate(
+ 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.Arm64.Negate(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.Arm64.Negate(
+ 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];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[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<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Negate(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.Negate)}<Int64>(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 NegateScalar_Vector64_Int64()
+ {
+ var test = new SimpleUnaryOpTest__NegateScalar_Vector64_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__NegateScalar_Vector64_Int64
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int64[] inArray1, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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 Vector64<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<Vector64<Int64>, byte>(ref testStruct._fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__NegateScalar_Vector64_Int64 testClass)
+ {
+ var result = AdvSimd.Arm64.NegateScalar(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__NegateScalar_Vector64_Int64 testClass)
+ {
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Arm64.NegateScalar(
+ AdvSimd.LoadVector64((Int64*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+
+ private static Vector64<Int64> _clsVar1;
+
+ private Vector64<Int64> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__NegateScalar_Vector64_Int64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ }
+
+ public SimpleUnaryOpTest__NegateScalar_Vector64_Int64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, new Int64[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.NegateScalar(
+ Unsafe.Read<Vector64<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.Arm64.NegateScalar(
+ AdvSimd.LoadVector64((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.Arm64).GetMethod(nameof(AdvSimd.Arm64.NegateScalar), new Type[] { typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.NegateScalar), new Type[] { typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.NegateScalar(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int64>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Arm64.NegateScalar(
+ AdvSimd.LoadVector64((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<Vector64<Int64>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Arm64.NegateScalar(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Arm64.NegateScalar(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__NegateScalar_Vector64_Int64();
+ var result = AdvSimd.Arm64.NegateScalar(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__NegateScalar_Vector64_Int64();
+
+ fixed (Vector64<Int64>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Arm64.NegateScalar(
+ AdvSimd.LoadVector64((Int64*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.NegateScalar(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Arm64.NegateScalar(
+ AdvSimd.LoadVector64((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.Arm64.NegateScalar(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.Arm64.NegateScalar(
+ AdvSimd.LoadVector64((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(Vector64<Int64> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (Helpers.Negate(firstOp[0]) != result[0])
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (result[i] != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.NegateScalar)}<Int64>(Vector64<Int64>): {method} failed:");
+ TestLibrary.TestFramework.LogInformation($" firstOp: ({string.Join(", ", firstOp)})");
+ TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
["CompareTestScalar.Vector64.Double"] = CompareTestScalar_Vector64_Double,
["CompareTestScalar.Vector64.Int64"] = CompareTestScalar_Vector64_Int64,
["CompareTestScalar.Vector64.UInt64"] = CompareTestScalar_Vector64_UInt64,
+ ["Divide.Vector64.Single"] = Divide_Vector64_Single,
+ ["Divide.Vector128.Double"] = Divide_Vector128_Double,
+ ["Divide.Vector128.Single"] = Divide_Vector128_Single,
+ ["Max.Vector128.Double"] = Max_Vector128_Double,
+ ["MaxScalar.Vector64.Double"] = MaxScalar_Vector64_Double,
+ ["MaxScalar.Vector64.Single"] = MaxScalar_Vector64_Single,
+ ["Min.Vector128.Double"] = Min_Vector128_Double,
+ ["MinScalar.Vector64.Double"] = MinScalar_Vector64_Double,
+ ["MinScalar.Vector64.Single"] = MinScalar_Vector64_Single,
+ ["Multiply.Vector128.Double"] = Multiply_Vector128_Double,
+ ["Negate.Vector128.Double"] = Negate_Vector128_Double,
+ ["Negate.Vector128.Int64"] = Negate_Vector128_Int64,
+ ["NegateScalar.Vector64.Int64"] = NegateScalar_Vector64_Int64,
["ReverseElementBits.Vector128.Byte"] = ReverseElementBits_Vector128_Byte,
["ReverseElementBits.Vector128.SByte"] = ReverseElementBits_Vector128_SByte,
["ReverseElementBits.Vector64.Byte"] = ReverseElementBits_Vector64_Byte,
["ReverseElementBits.Vector64.SByte"] = ReverseElementBits_Vector64_SByte,
+ ["Sqrt.Vector64.Single"] = Sqrt_Vector64_Single,
+ ["Sqrt.Vector128.Double"] = Sqrt_Vector128_Double,
+ ["Sqrt.Vector128.Single"] = Sqrt_Vector128_Single,
+ ["Subtract.Vector128.Double"] = Subtract_Vector128_Double,
["TransposeEven.Vector64.Byte"] = TransposeEven_Vector64_Byte,
["TransposeEven.Vector64.Int16"] = TransposeEven_Vector64_Int16,
["TransposeEven.Vector64.Int32"] = TransposeEven_Vector64_Int32,
--- /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 Sqrt_Vector128_Double()
+ {
+ var test = new SimpleUnaryOpTest__Sqrt_Vector128_Double();
+
+ 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__Sqrt_Vector128_Double
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, 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<Double> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Sqrt_Vector128_Double testClass)
+ {
+ var result = AdvSimd.Arm64.Sqrt(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Sqrt_Vector128_Double testClass)
+ {
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Arm64.Sqrt(
+ AdvSimd.LoadVector128((Double*)(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<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+
+ private Vector128<Double> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Sqrt_Vector128_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ }
+
+ public SimpleUnaryOpTest__Sqrt_Vector128_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.Sqrt(
+ Unsafe.Read<Vector128<Double>>(_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.Arm64.Sqrt(
+ AdvSimd.LoadVector128((Double*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.Sqrt), new Type[] { typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.Sqrt), new Type[] { typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.Sqrt(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Double>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Arm64.Sqrt(
+ AdvSimd.LoadVector128((Double*)(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<Double>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Arm64.Sqrt(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Arm64.Sqrt(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Sqrt_Vector128_Double();
+ var result = AdvSimd.Arm64.Sqrt(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__Sqrt_Vector128_Double();
+
+ fixed (Vector128<Double>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Arm64.Sqrt(
+ AdvSimd.LoadVector128((Double*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.Sqrt(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Arm64.Sqrt(
+ AdvSimd.LoadVector128((Double*)(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.Arm64.Sqrt(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.Arm64.Sqrt(
+ AdvSimd.LoadVector128((Double*)(&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<Double> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.Sqrt(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.Sqrt)}<Double>(Vector128<Double>): {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 Sqrt_Vector128_Single()
+ {
+ var test = new SimpleUnaryOpTest__Sqrt_Vector128_Single();
+
+ 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__Sqrt_Vector128_Single
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, 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<Single> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Sqrt_Vector128_Single testClass)
+ {
+ var result = AdvSimd.Arm64.Sqrt(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Sqrt_Vector128_Single testClass)
+ {
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Arm64.Sqrt(
+ AdvSimd.LoadVector128((Single*)(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<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+
+ private Vector128<Single> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Sqrt_Vector128_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ }
+
+ public SimpleUnaryOpTest__Sqrt_Vector128_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.Sqrt(
+ Unsafe.Read<Vector128<Single>>(_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.Arm64.Sqrt(
+ AdvSimd.LoadVector128((Single*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.Sqrt), new Type[] { typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.Sqrt), new Type[] { typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.Sqrt(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Single>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Arm64.Sqrt(
+ AdvSimd.LoadVector128((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Arm64.Sqrt(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Arm64.Sqrt(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Sqrt_Vector128_Single();
+ var result = AdvSimd.Arm64.Sqrt(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__Sqrt_Vector128_Single();
+
+ fixed (Vector128<Single>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Arm64.Sqrt(
+ AdvSimd.LoadVector128((Single*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.Sqrt(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Arm64.Sqrt(
+ AdvSimd.LoadVector128((Single*)(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.Arm64.Sqrt(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.Arm64.Sqrt(
+ AdvSimd.LoadVector128((Single*)(&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<Single> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.Sqrt)}<Single>(Vector128<Single>): {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 Sqrt_Vector64_Single()
+ {
+ var test = new SimpleUnaryOpTest__Sqrt_Vector64_Single();
+
+ 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__Sqrt_Vector64_Single
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, 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 Vector64<Single> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Sqrt_Vector64_Single testClass)
+ {
+ var result = AdvSimd.Arm64.Sqrt(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Sqrt_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Arm64.Sqrt(
+ AdvSimd.LoadVector64((Single*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+
+ private Vector64<Single> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Sqrt_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleUnaryOpTest__Sqrt_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, new Single[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.Sqrt(
+ Unsafe.Read<Vector64<Single>>(_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.Arm64.Sqrt(
+ AdvSimd.LoadVector64((Single*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.Sqrt), new Type[] { typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.Sqrt), new Type[] { typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.Sqrt(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Arm64.Sqrt(
+ AdvSimd.LoadVector64((Single*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Arm64.Sqrt(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Arm64.Sqrt(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Sqrt_Vector64_Single();
+ var result = AdvSimd.Arm64.Sqrt(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__Sqrt_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Arm64.Sqrt(
+ AdvSimd.LoadVector64((Single*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.Sqrt(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Arm64.Sqrt(
+ AdvSimd.LoadVector64((Single*)(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.Arm64.Sqrt(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.Arm64.Sqrt(
+ AdvSimd.LoadVector64((Single*)(&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(Vector64<Single> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.Sqrt)}<Single>(Vector64<Single>): {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 Subtract_Vector128_Double()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_Double();
+
+ 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__Subtract_Vector128_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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 Vector128<Double> _fld1;
+ public Vector128<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Subtract_Vector128_Double testClass)
+ {
+ var result = AdvSimd.Arm64.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector128_Double testClass)
+ {
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Subtract(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+ private static Vector128<Double> _clsVar2;
+
+ private Vector128<Double> _fld1;
+ private Vector128<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_Vector128_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ }
+
+ public SimpleBinaryOpTest__Subtract_Vector128_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
+ }
+
+ public bool IsSupported => AdvSimd.Arm64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = AdvSimd.Arm64.Subtract(
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_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.Arm64.Subtract(
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_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.Arm64).GetMethod(nameof(AdvSimd.Arm64.Subtract), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd.Arm64).GetMethod(nameof(AdvSimd.Arm64.Subtract), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Arm64.Subtract(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Arm64.Subtract(
+ AdvSimd.LoadVector128((Double*)(pClsVar1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Arm64.Subtract(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.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Arm64.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_Double();
+ var result = AdvSimd.Arm64.Subtract(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__Subtract_Vector128_Double();
+
+ fixed (Vector128<Double>* pFld1 = &test._fld1)
+ fixed (Vector128<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Arm64.Subtract(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Arm64.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Arm64.Subtract(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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.Arm64.Subtract(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.Arm64.Subtract(
+ AdvSimd.LoadVector128((Double*)(&test._fld1)),
+ AdvSimd.LoadVector128((Double*)(&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(Vector128<Double> op1, Vector128<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.Subtract(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd.Arm64)}.{nameof(AdvSimd.Arm64.Subtract)}<Double>(Vector128<Double>, Vector128<Double>): {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;
+ }
+ }
+ }
+}
<Compile Include="AddScalar.Vector64.Int64.cs" />
<Compile Include="AddScalar.Vector64.Single.cs" />
<Compile Include="AddScalar.Vector64.UInt64.cs" />
+ <Compile Include="And.Vector64.Byte.cs" />
+ <Compile Include="And.Vector64.Double.cs" />
+ <Compile Include="And.Vector64.Int16.cs" />
+ <Compile Include="And.Vector64.Int32.cs" />
+ <Compile Include="And.Vector64.Int64.cs" />
+ <Compile Include="And.Vector64.SByte.cs" />
+ <Compile Include="And.Vector64.Single.cs" />
+ <Compile Include="And.Vector64.UInt16.cs" />
+ <Compile Include="And.Vector64.UInt32.cs" />
+ <Compile Include="And.Vector64.UInt64.cs" />
+ <Compile Include="And.Vector128.Byte.cs" />
+ <Compile Include="And.Vector128.Double.cs" />
+ <Compile Include="And.Vector128.Int16.cs" />
+ <Compile Include="And.Vector128.Int32.cs" />
+ <Compile Include="And.Vector128.Int64.cs" />
+ <Compile Include="And.Vector128.SByte.cs" />
+ <Compile Include="And.Vector128.Single.cs" />
+ <Compile Include="And.Vector128.UInt16.cs" />
+ <Compile Include="And.Vector128.UInt32.cs" />
+ <Compile Include="And.Vector128.UInt64.cs" />
+ <Compile Include="BitwiseClear.Vector64.Byte.cs" />
+ <Compile Include="BitwiseClear.Vector64.Double.cs" />
+ <Compile Include="BitwiseClear.Vector64.Int16.cs" />
+ <Compile Include="BitwiseClear.Vector64.Int32.cs" />
+ <Compile Include="BitwiseClear.Vector64.Int64.cs" />
+ <Compile Include="BitwiseClear.Vector64.SByte.cs" />
+ <Compile Include="BitwiseClear.Vector64.Single.cs" />
+ <Compile Include="BitwiseClear.Vector64.UInt16.cs" />
+ <Compile Include="BitwiseClear.Vector64.UInt32.cs" />
+ <Compile Include="BitwiseClear.Vector64.UInt64.cs" />
+ <Compile Include="BitwiseClear.Vector128.Byte.cs" />
+ <Compile Include="BitwiseClear.Vector128.Double.cs" />
+ <Compile Include="BitwiseClear.Vector128.Int16.cs" />
+ <Compile Include="BitwiseClear.Vector128.Int32.cs" />
+ <Compile Include="BitwiseClear.Vector128.Int64.cs" />
+ <Compile Include="BitwiseClear.Vector128.SByte.cs" />
+ <Compile Include="BitwiseClear.Vector128.Single.cs" />
+ <Compile Include="BitwiseClear.Vector128.UInt16.cs" />
+ <Compile Include="BitwiseClear.Vector128.UInt32.cs" />
+ <Compile Include="BitwiseClear.Vector128.UInt64.cs" />
<Compile Include="BitwiseSelect.Vector64.Byte.cs" />
<Compile Include="BitwiseSelect.Vector64.Double.cs" />
<Compile Include="BitwiseSelect.Vector64.Int16.cs" />
<Compile Include="CompareTest.Vector128.Single.cs" />
<Compile Include="CompareTest.Vector128.UInt16.cs" />
<Compile Include="CompareTest.Vector128.UInt32.cs" />
+ <Compile Include="DivideScalar.Vector64.Double.cs" />
+ <Compile Include="DivideScalar.Vector64.Single.cs" />
<Compile Include="LeadingSignCount.Vector64.Int16.cs" />
<Compile Include="LeadingSignCount.Vector64.Int32.cs" />
<Compile Include="LeadingSignCount.Vector64.SByte.cs" />
<Compile Include="LoadVector128.UInt16.cs" />
<Compile Include="LoadVector128.UInt32.cs" />
<Compile Include="LoadVector128.UInt64.cs" />
+ <Compile Include="Max.Vector64.Byte.cs" />
+ <Compile Include="Max.Vector64.Int16.cs" />
+ <Compile Include="Max.Vector64.Int32.cs" />
+ <Compile Include="Max.Vector64.SByte.cs" />
+ <Compile Include="Max.Vector64.Single.cs" />
+ <Compile Include="Max.Vector64.UInt16.cs" />
+ <Compile Include="Max.Vector64.UInt32.cs" />
+ <Compile Include="Max.Vector128.Byte.cs" />
+ <Compile Include="Max.Vector128.Int16.cs" />
+ <Compile Include="Max.Vector128.Int32.cs" />
+ <Compile Include="Max.Vector128.SByte.cs" />
+ <Compile Include="Max.Vector128.Single.cs" />
+ <Compile Include="Max.Vector128.UInt16.cs" />
+ <Compile Include="Max.Vector128.UInt32.cs" />
+ <Compile Include="Min.Vector64.Byte.cs" />
+ <Compile Include="Min.Vector64.Int16.cs" />
+ <Compile Include="Min.Vector64.Int32.cs" />
+ <Compile Include="Min.Vector64.SByte.cs" />
+ <Compile Include="Min.Vector64.Single.cs" />
+ <Compile Include="Min.Vector64.UInt16.cs" />
+ <Compile Include="Min.Vector64.UInt32.cs" />
+ <Compile Include="Min.Vector128.Byte.cs" />
+ <Compile Include="Min.Vector128.Int16.cs" />
+ <Compile Include="Min.Vector128.Int32.cs" />
+ <Compile Include="Min.Vector128.SByte.cs" />
+ <Compile Include="Min.Vector128.Single.cs" />
+ <Compile Include="Min.Vector128.UInt16.cs" />
+ <Compile Include="Min.Vector128.UInt32.cs" />
+ <Compile Include="Multiply.Vector64.Byte.cs" />
+ <Compile Include="Multiply.Vector64.Int16.cs" />
+ <Compile Include="Multiply.Vector64.Int32.cs" />
+ <Compile Include="Multiply.Vector64.SByte.cs" />
+ <Compile Include="Multiply.Vector64.Single.cs" />
+ <Compile Include="Multiply.Vector64.UInt16.cs" />
+ <Compile Include="Multiply.Vector64.UInt32.cs" />
+ <Compile Include="Multiply.Vector128.Byte.cs" />
+ <Compile Include="Multiply.Vector128.Int16.cs" />
+ <Compile Include="Multiply.Vector128.Int32.cs" />
+ <Compile Include="Multiply.Vector128.SByte.cs" />
+ <Compile Include="Multiply.Vector128.Single.cs" />
+ <Compile Include="Multiply.Vector128.UInt16.cs" />
+ <Compile Include="Multiply.Vector128.UInt32.cs" />
+ <Compile Include="MultiplyScalar.Vector64.Double.cs" />
+ <Compile Include="MultiplyScalar.Vector64.Single.cs" />
+ <Compile Include="Negate.Vector64.Int16.cs" />
+ <Compile Include="Negate.Vector64.Int32.cs" />
+ <Compile Include="Negate.Vector64.SByte.cs" />
+ <Compile Include="Negate.Vector64.Single.cs" />
+ <Compile Include="Negate.Vector128.Int16.cs" />
+ <Compile Include="Negate.Vector128.Int32.cs" />
+ <Compile Include="Negate.Vector128.SByte.cs" />
+ <Compile Include="Negate.Vector128.Single.cs" />
+ <Compile Include="NegateScalar.Vector64.Double.cs" />
+ <Compile Include="NegateScalar.Vector64.Single.cs" />
+ <Compile Include="Not.Vector64.Byte.cs" />
+ <Compile Include="Not.Vector64.Double.cs" />
+ <Compile Include="Not.Vector64.Int16.cs" />
+ <Compile Include="Not.Vector64.Int32.cs" />
+ <Compile Include="Not.Vector64.Int64.cs" />
+ <Compile Include="Not.Vector64.SByte.cs" />
+ <Compile Include="Not.Vector64.Single.cs" />
+ <Compile Include="Not.Vector64.UInt16.cs" />
+ <Compile Include="Not.Vector64.UInt32.cs" />
+ <Compile Include="Not.Vector64.UInt64.cs" />
+ <Compile Include="Not.Vector128.Byte.cs" />
+ <Compile Include="Not.Vector128.Double.cs" />
+ <Compile Include="Not.Vector128.Int16.cs" />
+ <Compile Include="Not.Vector128.Int32.cs" />
+ <Compile Include="Not.Vector128.Int64.cs" />
+ <Compile Include="Not.Vector128.SByte.cs" />
+ <Compile Include="Not.Vector128.Single.cs" />
+ <Compile Include="Not.Vector128.UInt16.cs" />
+ <Compile Include="Not.Vector128.UInt32.cs" />
+ <Compile Include="Not.Vector128.UInt64.cs" />
+ <Compile Include="Or.Vector64.Byte.cs" />
+ <Compile Include="Or.Vector64.Double.cs" />
+ <Compile Include="Or.Vector64.Int16.cs" />
+ <Compile Include="Or.Vector64.Int32.cs" />
+ <Compile Include="Or.Vector64.Int64.cs" />
+ <Compile Include="Or.Vector64.SByte.cs" />
+ <Compile Include="Or.Vector64.Single.cs" />
+ <Compile Include="Or.Vector64.UInt16.cs" />
+ <Compile Include="Or.Vector64.UInt32.cs" />
+ <Compile Include="Or.Vector64.UInt64.cs" />
+ <Compile Include="Or.Vector128.Byte.cs" />
+ <Compile Include="Or.Vector128.Double.cs" />
+ <Compile Include="Or.Vector128.Int16.cs" />
+ <Compile Include="Or.Vector128.Int32.cs" />
+ <Compile Include="Or.Vector128.Int64.cs" />
+ <Compile Include="Or.Vector128.SByte.cs" />
+ <Compile Include="Or.Vector128.Single.cs" />
+ <Compile Include="Or.Vector128.UInt16.cs" />
+ <Compile Include="Or.Vector128.UInt32.cs" />
+ <Compile Include="Or.Vector128.UInt64.cs" />
+ <Compile Include="OrNot.Vector64.Byte.cs" />
+ <Compile Include="OrNot.Vector64.Double.cs" />
+ <Compile Include="OrNot.Vector64.Int16.cs" />
+ <Compile Include="OrNot.Vector64.Int32.cs" />
+ <Compile Include="OrNot.Vector64.Int64.cs" />
+ <Compile Include="OrNot.Vector64.SByte.cs" />
+ <Compile Include="OrNot.Vector64.Single.cs" />
+ <Compile Include="OrNot.Vector64.UInt16.cs" />
+ <Compile Include="OrNot.Vector64.UInt32.cs" />
+ <Compile Include="OrNot.Vector64.UInt64.cs" />
+ <Compile Include="OrNot.Vector128.Byte.cs" />
+ <Compile Include="OrNot.Vector128.Double.cs" />
+ <Compile Include="OrNot.Vector128.Int16.cs" />
+ <Compile Include="OrNot.Vector128.Int32.cs" />
+ <Compile Include="OrNot.Vector128.Int64.cs" />
+ <Compile Include="OrNot.Vector128.SByte.cs" />
+ <Compile Include="OrNot.Vector128.Single.cs" />
+ <Compile Include="OrNot.Vector128.UInt16.cs" />
+ <Compile Include="OrNot.Vector128.UInt32.cs" />
+ <Compile Include="OrNot.Vector128.UInt64.cs" />
<Compile Include="PopCount.Vector64.Byte.cs" />
<Compile Include="PopCount.Vector64.SByte.cs" />
<Compile Include="PopCount.Vector128.Byte.cs" />
<Compile Include="PopCount.Vector128.SByte.cs" />
+ <Compile Include="SqrtScalar.Vector64.Double.cs" />
+ <Compile Include="SqrtScalar.Vector64.Single.cs" />
+ <Compile Include="Subtract.Vector64.Byte.cs" />
+ <Compile Include="Subtract.Vector64.Int16.cs" />
+ <Compile Include="Subtract.Vector64.Int32.cs" />
+ <Compile Include="Subtract.Vector64.SByte.cs" />
+ <Compile Include="Subtract.Vector64.Single.cs" />
+ <Compile Include="Subtract.Vector64.UInt16.cs" />
+ <Compile Include="Subtract.Vector64.UInt32.cs" />
+ <Compile Include="Subtract.Vector128.Byte.cs" />
+ <Compile Include="Subtract.Vector128.Int16.cs" />
+ <Compile Include="Subtract.Vector128.Int32.cs" />
+ <Compile Include="Subtract.Vector128.Int64.cs" />
+ <Compile Include="Subtract.Vector128.SByte.cs" />
+ <Compile Include="Subtract.Vector128.Single.cs" />
+ <Compile Include="Subtract.Vector128.UInt16.cs" />
+ <Compile Include="Subtract.Vector128.UInt32.cs" />
+ <Compile Include="Subtract.Vector128.UInt64.cs" />
+ <Compile Include="SubtractScalar.Vector64.Double.cs" />
+ <Compile Include="SubtractScalar.Vector64.Int64.cs" />
+ <Compile Include="SubtractScalar.Vector64.Single.cs" />
+ <Compile Include="SubtractScalar.Vector64.UInt64.cs" />
+ <Compile Include="Xor.Vector64.Byte.cs" />
+ <Compile Include="Xor.Vector64.Double.cs" />
+ <Compile Include="Xor.Vector64.Int16.cs" />
+ <Compile Include="Xor.Vector64.Int32.cs" />
+ <Compile Include="Xor.Vector64.Int64.cs" />
+ <Compile Include="Xor.Vector64.SByte.cs" />
+ <Compile Include="Xor.Vector64.Single.cs" />
+ <Compile Include="Xor.Vector64.UInt16.cs" />
+ <Compile Include="Xor.Vector64.UInt32.cs" />
+ <Compile Include="Xor.Vector64.UInt64.cs" />
+ <Compile Include="Xor.Vector128.Byte.cs" />
+ <Compile Include="Xor.Vector128.Double.cs" />
+ <Compile Include="Xor.Vector128.Int16.cs" />
+ <Compile Include="Xor.Vector128.Int32.cs" />
+ <Compile Include="Xor.Vector128.Int64.cs" />
+ <Compile Include="Xor.Vector128.SByte.cs" />
+ <Compile Include="Xor.Vector128.Single.cs" />
+ <Compile Include="Xor.Vector128.UInt16.cs" />
+ <Compile Include="Xor.Vector128.UInt32.cs" />
+ <Compile Include="Xor.Vector128.UInt64.cs" />
<Compile Include="Program.AdvSimd.cs" />
<Compile Include="..\Shared\Helpers.cs" />
<Compile Include="..\Shared\Program.cs" />
<Compile Include="AddScalar.Vector64.Int64.cs" />
<Compile Include="AddScalar.Vector64.Single.cs" />
<Compile Include="AddScalar.Vector64.UInt64.cs" />
+ <Compile Include="And.Vector64.Byte.cs" />
+ <Compile Include="And.Vector64.Double.cs" />
+ <Compile Include="And.Vector64.Int16.cs" />
+ <Compile Include="And.Vector64.Int32.cs" />
+ <Compile Include="And.Vector64.Int64.cs" />
+ <Compile Include="And.Vector64.SByte.cs" />
+ <Compile Include="And.Vector64.Single.cs" />
+ <Compile Include="And.Vector64.UInt16.cs" />
+ <Compile Include="And.Vector64.UInt32.cs" />
+ <Compile Include="And.Vector64.UInt64.cs" />
+ <Compile Include="And.Vector128.Byte.cs" />
+ <Compile Include="And.Vector128.Double.cs" />
+ <Compile Include="And.Vector128.Int16.cs" />
+ <Compile Include="And.Vector128.Int32.cs" />
+ <Compile Include="And.Vector128.Int64.cs" />
+ <Compile Include="And.Vector128.SByte.cs" />
+ <Compile Include="And.Vector128.Single.cs" />
+ <Compile Include="And.Vector128.UInt16.cs" />
+ <Compile Include="And.Vector128.UInt32.cs" />
+ <Compile Include="And.Vector128.UInt64.cs" />
+ <Compile Include="BitwiseClear.Vector64.Byte.cs" />
+ <Compile Include="BitwiseClear.Vector64.Double.cs" />
+ <Compile Include="BitwiseClear.Vector64.Int16.cs" />
+ <Compile Include="BitwiseClear.Vector64.Int32.cs" />
+ <Compile Include="BitwiseClear.Vector64.Int64.cs" />
+ <Compile Include="BitwiseClear.Vector64.SByte.cs" />
+ <Compile Include="BitwiseClear.Vector64.Single.cs" />
+ <Compile Include="BitwiseClear.Vector64.UInt16.cs" />
+ <Compile Include="BitwiseClear.Vector64.UInt32.cs" />
+ <Compile Include="BitwiseClear.Vector64.UInt64.cs" />
+ <Compile Include="BitwiseClear.Vector128.Byte.cs" />
+ <Compile Include="BitwiseClear.Vector128.Double.cs" />
+ <Compile Include="BitwiseClear.Vector128.Int16.cs" />
+ <Compile Include="BitwiseClear.Vector128.Int32.cs" />
+ <Compile Include="BitwiseClear.Vector128.Int64.cs" />
+ <Compile Include="BitwiseClear.Vector128.SByte.cs" />
+ <Compile Include="BitwiseClear.Vector128.Single.cs" />
+ <Compile Include="BitwiseClear.Vector128.UInt16.cs" />
+ <Compile Include="BitwiseClear.Vector128.UInt32.cs" />
+ <Compile Include="BitwiseClear.Vector128.UInt64.cs" />
<Compile Include="BitwiseSelect.Vector64.Byte.cs" />
<Compile Include="BitwiseSelect.Vector64.Double.cs" />
<Compile Include="BitwiseSelect.Vector64.Int16.cs" />
<Compile Include="CompareTest.Vector128.Single.cs" />
<Compile Include="CompareTest.Vector128.UInt16.cs" />
<Compile Include="CompareTest.Vector128.UInt32.cs" />
+ <Compile Include="DivideScalar.Vector64.Double.cs" />
+ <Compile Include="DivideScalar.Vector64.Single.cs" />
<Compile Include="LeadingSignCount.Vector64.Int16.cs" />
<Compile Include="LeadingSignCount.Vector64.Int32.cs" />
<Compile Include="LeadingSignCount.Vector64.SByte.cs" />
<Compile Include="LoadVector128.UInt16.cs" />
<Compile Include="LoadVector128.UInt32.cs" />
<Compile Include="LoadVector128.UInt64.cs" />
+ <Compile Include="Max.Vector64.Byte.cs" />
+ <Compile Include="Max.Vector64.Int16.cs" />
+ <Compile Include="Max.Vector64.Int32.cs" />
+ <Compile Include="Max.Vector64.SByte.cs" />
+ <Compile Include="Max.Vector64.Single.cs" />
+ <Compile Include="Max.Vector64.UInt16.cs" />
+ <Compile Include="Max.Vector64.UInt32.cs" />
+ <Compile Include="Max.Vector128.Byte.cs" />
+ <Compile Include="Max.Vector128.Int16.cs" />
+ <Compile Include="Max.Vector128.Int32.cs" />
+ <Compile Include="Max.Vector128.SByte.cs" />
+ <Compile Include="Max.Vector128.Single.cs" />
+ <Compile Include="Max.Vector128.UInt16.cs" />
+ <Compile Include="Max.Vector128.UInt32.cs" />
+ <Compile Include="Min.Vector64.Byte.cs" />
+ <Compile Include="Min.Vector64.Int16.cs" />
+ <Compile Include="Min.Vector64.Int32.cs" />
+ <Compile Include="Min.Vector64.SByte.cs" />
+ <Compile Include="Min.Vector64.Single.cs" />
+ <Compile Include="Min.Vector64.UInt16.cs" />
+ <Compile Include="Min.Vector64.UInt32.cs" />
+ <Compile Include="Min.Vector128.Byte.cs" />
+ <Compile Include="Min.Vector128.Int16.cs" />
+ <Compile Include="Min.Vector128.Int32.cs" />
+ <Compile Include="Min.Vector128.SByte.cs" />
+ <Compile Include="Min.Vector128.Single.cs" />
+ <Compile Include="Min.Vector128.UInt16.cs" />
+ <Compile Include="Min.Vector128.UInt32.cs" />
+ <Compile Include="Multiply.Vector64.Byte.cs" />
+ <Compile Include="Multiply.Vector64.Int16.cs" />
+ <Compile Include="Multiply.Vector64.Int32.cs" />
+ <Compile Include="Multiply.Vector64.SByte.cs" />
+ <Compile Include="Multiply.Vector64.Single.cs" />
+ <Compile Include="Multiply.Vector64.UInt16.cs" />
+ <Compile Include="Multiply.Vector64.UInt32.cs" />
+ <Compile Include="Multiply.Vector128.Byte.cs" />
+ <Compile Include="Multiply.Vector128.Int16.cs" />
+ <Compile Include="Multiply.Vector128.Int32.cs" />
+ <Compile Include="Multiply.Vector128.SByte.cs" />
+ <Compile Include="Multiply.Vector128.Single.cs" />
+ <Compile Include="Multiply.Vector128.UInt16.cs" />
+ <Compile Include="Multiply.Vector128.UInt32.cs" />
+ <Compile Include="MultiplyScalar.Vector64.Double.cs" />
+ <Compile Include="MultiplyScalar.Vector64.Single.cs" />
+ <Compile Include="Negate.Vector64.Int16.cs" />
+ <Compile Include="Negate.Vector64.Int32.cs" />
+ <Compile Include="Negate.Vector64.SByte.cs" />
+ <Compile Include="Negate.Vector64.Single.cs" />
+ <Compile Include="Negate.Vector128.Int16.cs" />
+ <Compile Include="Negate.Vector128.Int32.cs" />
+ <Compile Include="Negate.Vector128.SByte.cs" />
+ <Compile Include="Negate.Vector128.Single.cs" />
+ <Compile Include="NegateScalar.Vector64.Double.cs" />
+ <Compile Include="NegateScalar.Vector64.Single.cs" />
+ <Compile Include="Not.Vector64.Byte.cs" />
+ <Compile Include="Not.Vector64.Double.cs" />
+ <Compile Include="Not.Vector64.Int16.cs" />
+ <Compile Include="Not.Vector64.Int32.cs" />
+ <Compile Include="Not.Vector64.Int64.cs" />
+ <Compile Include="Not.Vector64.SByte.cs" />
+ <Compile Include="Not.Vector64.Single.cs" />
+ <Compile Include="Not.Vector64.UInt16.cs" />
+ <Compile Include="Not.Vector64.UInt32.cs" />
+ <Compile Include="Not.Vector64.UInt64.cs" />
+ <Compile Include="Not.Vector128.Byte.cs" />
+ <Compile Include="Not.Vector128.Double.cs" />
+ <Compile Include="Not.Vector128.Int16.cs" />
+ <Compile Include="Not.Vector128.Int32.cs" />
+ <Compile Include="Not.Vector128.Int64.cs" />
+ <Compile Include="Not.Vector128.SByte.cs" />
+ <Compile Include="Not.Vector128.Single.cs" />
+ <Compile Include="Not.Vector128.UInt16.cs" />
+ <Compile Include="Not.Vector128.UInt32.cs" />
+ <Compile Include="Not.Vector128.UInt64.cs" />
+ <Compile Include="Or.Vector64.Byte.cs" />
+ <Compile Include="Or.Vector64.Double.cs" />
+ <Compile Include="Or.Vector64.Int16.cs" />
+ <Compile Include="Or.Vector64.Int32.cs" />
+ <Compile Include="Or.Vector64.Int64.cs" />
+ <Compile Include="Or.Vector64.SByte.cs" />
+ <Compile Include="Or.Vector64.Single.cs" />
+ <Compile Include="Or.Vector64.UInt16.cs" />
+ <Compile Include="Or.Vector64.UInt32.cs" />
+ <Compile Include="Or.Vector64.UInt64.cs" />
+ <Compile Include="Or.Vector128.Byte.cs" />
+ <Compile Include="Or.Vector128.Double.cs" />
+ <Compile Include="Or.Vector128.Int16.cs" />
+ <Compile Include="Or.Vector128.Int32.cs" />
+ <Compile Include="Or.Vector128.Int64.cs" />
+ <Compile Include="Or.Vector128.SByte.cs" />
+ <Compile Include="Or.Vector128.Single.cs" />
+ <Compile Include="Or.Vector128.UInt16.cs" />
+ <Compile Include="Or.Vector128.UInt32.cs" />
+ <Compile Include="Or.Vector128.UInt64.cs" />
+ <Compile Include="OrNot.Vector64.Byte.cs" />
+ <Compile Include="OrNot.Vector64.Double.cs" />
+ <Compile Include="OrNot.Vector64.Int16.cs" />
+ <Compile Include="OrNot.Vector64.Int32.cs" />
+ <Compile Include="OrNot.Vector64.Int64.cs" />
+ <Compile Include="OrNot.Vector64.SByte.cs" />
+ <Compile Include="OrNot.Vector64.Single.cs" />
+ <Compile Include="OrNot.Vector64.UInt16.cs" />
+ <Compile Include="OrNot.Vector64.UInt32.cs" />
+ <Compile Include="OrNot.Vector64.UInt64.cs" />
+ <Compile Include="OrNot.Vector128.Byte.cs" />
+ <Compile Include="OrNot.Vector128.Double.cs" />
+ <Compile Include="OrNot.Vector128.Int16.cs" />
+ <Compile Include="OrNot.Vector128.Int32.cs" />
+ <Compile Include="OrNot.Vector128.Int64.cs" />
+ <Compile Include="OrNot.Vector128.SByte.cs" />
+ <Compile Include="OrNot.Vector128.Single.cs" />
+ <Compile Include="OrNot.Vector128.UInt16.cs" />
+ <Compile Include="OrNot.Vector128.UInt32.cs" />
+ <Compile Include="OrNot.Vector128.UInt64.cs" />
<Compile Include="PopCount.Vector64.Byte.cs" />
<Compile Include="PopCount.Vector64.SByte.cs" />
<Compile Include="PopCount.Vector128.Byte.cs" />
<Compile Include="PopCount.Vector128.SByte.cs" />
+ <Compile Include="SqrtScalar.Vector64.Double.cs" />
+ <Compile Include="SqrtScalar.Vector64.Single.cs" />
+ <Compile Include="Subtract.Vector64.Byte.cs" />
+ <Compile Include="Subtract.Vector64.Int16.cs" />
+ <Compile Include="Subtract.Vector64.Int32.cs" />
+ <Compile Include="Subtract.Vector64.SByte.cs" />
+ <Compile Include="Subtract.Vector64.Single.cs" />
+ <Compile Include="Subtract.Vector64.UInt16.cs" />
+ <Compile Include="Subtract.Vector64.UInt32.cs" />
+ <Compile Include="Subtract.Vector128.Byte.cs" />
+ <Compile Include="Subtract.Vector128.Int16.cs" />
+ <Compile Include="Subtract.Vector128.Int32.cs" />
+ <Compile Include="Subtract.Vector128.Int64.cs" />
+ <Compile Include="Subtract.Vector128.SByte.cs" />
+ <Compile Include="Subtract.Vector128.Single.cs" />
+ <Compile Include="Subtract.Vector128.UInt16.cs" />
+ <Compile Include="Subtract.Vector128.UInt32.cs" />
+ <Compile Include="Subtract.Vector128.UInt64.cs" />
+ <Compile Include="SubtractScalar.Vector64.Double.cs" />
+ <Compile Include="SubtractScalar.Vector64.Int64.cs" />
+ <Compile Include="SubtractScalar.Vector64.Single.cs" />
+ <Compile Include="SubtractScalar.Vector64.UInt64.cs" />
+ <Compile Include="Xor.Vector64.Byte.cs" />
+ <Compile Include="Xor.Vector64.Double.cs" />
+ <Compile Include="Xor.Vector64.Int16.cs" />
+ <Compile Include="Xor.Vector64.Int32.cs" />
+ <Compile Include="Xor.Vector64.Int64.cs" />
+ <Compile Include="Xor.Vector64.SByte.cs" />
+ <Compile Include="Xor.Vector64.Single.cs" />
+ <Compile Include="Xor.Vector64.UInt16.cs" />
+ <Compile Include="Xor.Vector64.UInt32.cs" />
+ <Compile Include="Xor.Vector64.UInt64.cs" />
+ <Compile Include="Xor.Vector128.Byte.cs" />
+ <Compile Include="Xor.Vector128.Double.cs" />
+ <Compile Include="Xor.Vector128.Int16.cs" />
+ <Compile Include="Xor.Vector128.Int32.cs" />
+ <Compile Include="Xor.Vector128.Int64.cs" />
+ <Compile Include="Xor.Vector128.SByte.cs" />
+ <Compile Include="Xor.Vector128.Single.cs" />
+ <Compile Include="Xor.Vector128.UInt16.cs" />
+ <Compile Include="Xor.Vector128.UInt32.cs" />
+ <Compile Include="Xor.Vector128.UInt64.cs" />
<Compile Include="Program.AdvSimd.cs" />
<Compile Include="..\Shared\Helpers.cs" />
<Compile Include="..\Shared\Program.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 And_Vector128_Byte()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector128_Byte();
+
+ 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__And_Vector128_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector128<Byte> _fld1;
+ public Vector128<Byte> _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<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector128_Byte testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector128_Byte testClass)
+ {
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector128<Byte> _clsVar1;
+ private static Vector128<Byte> _clsVar2;
+
+ private Vector128<Byte> _fld1;
+ private Vector128<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector128_Byte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector128_Byte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.And(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.And(
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.And), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.And), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Byte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector128((Byte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector128_Byte();
+ var result = AdvSimd.And(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__And_Vector128_Byte();
+
+ fixed (Vector128<Byte>* pFld1 = &test._fld1)
+ fixed (Vector128<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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.And(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.And(
+ AdvSimd.LoadVector128((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector128((Byte*)(&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(Vector128<Byte> op1, Vector128<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, 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];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ 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, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<Byte>(Vector128<Byte>, Vector128<Byte>): {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 And_Vector128_Double()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector128_Double();
+
+ 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__And_Vector128_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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 Vector128<Double> _fld1;
+ public Vector128<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector128_Double testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector128_Double testClass)
+ {
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+ private static Vector128<Double> _clsVar2;
+
+ private Vector128<Double> _fld1;
+ private Vector128<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector128_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector128_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[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.And(
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_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.And(
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_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.And), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(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.And), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Double*)(pClsVar1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector128_Double();
+ var result = AdvSimd.And(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__And_Vector128_Double();
+
+ fixed (Vector128<Double>* pFld1 = &test._fld1)
+ fixed (Vector128<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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.And(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.And(
+ AdvSimd.LoadVector128((Double*)(&test._fld1)),
+ AdvSimd.LoadVector128((Double*)(&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(Vector128<Double> op1, Vector128<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.And(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<Double>(Vector128<Double>, Vector128<Double>): {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 And_Vector128_Int16()
+ {
+ var test = new SimpleBinaryOpTest__And_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__And_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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 Vector128<Int16> _fld1;
+ public Vector128<Int16> _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<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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__And_Vector128_Int16 testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector128_Int16 testClass)
+ {
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector128<Int16> _clsVar1;
+ private static Vector128<Int16> _clsVar2;
+
+ private Vector128<Int16> _fld1;
+ private Vector128<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_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>>());
+ 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__And_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 < 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.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.And(
+ Unsafe.Read<Vector128<Int16>>(_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.And(
+ AdvSimd.LoadVector128((Int16*)(_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.And), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int16>>(_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.And), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int16*)(_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.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector128((Int16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector128_Int16();
+ var result = AdvSimd.And(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__And_Vector128_Int16();
+
+ fixed (Vector128<Int16>* pFld1 = &test._fld1)
+ fixed (Vector128<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Int16*)(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.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Int16*)(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.And(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.And(
+ AdvSimd.LoadVector128((Int16*)(&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(Vector128<Int16> op1, Vector128<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, 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];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<Int16>(Vector128<Int16>, 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 And_Vector128_Int32()
+ {
+ var test = new SimpleBinaryOpTest__And_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__And_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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 Vector128<Int32> _fld1;
+ public Vector128<Int32> _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<Vector128<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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__And_Vector128_Int32 testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector128_Int32 testClass)
+ {
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector128<Int32> _clsVar1;
+ private static Vector128<Int32> _clsVar2;
+
+ private Vector128<Int32> _fld1;
+ private Vector128<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_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>>());
+ 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__And_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 < 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.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.And(
+ Unsafe.Read<Vector128<Int32>>(_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.And(
+ AdvSimd.LoadVector128((Int32*)(_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.And), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int32>>(_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.And), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int32*)(_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.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector128((Int32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector128_Int32();
+ var result = AdvSimd.And(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__And_Vector128_Int32();
+
+ fixed (Vector128<Int32>* pFld1 = &test._fld1)
+ fixed (Vector128<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Int32*)(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.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Int32*)(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.And(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.And(
+ AdvSimd.LoadVector128((Int32*)(&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(Vector128<Int32> op1, Vector128<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, 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];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<Int32>(Vector128<Int32>, 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 And_Vector128_Int64()
+ {
+ var test = new SimpleBinaryOpTest__And_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__And_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(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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<Int64, 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 Vector128<Int64> _fld1;
+ public Vector128<Int64> _fld2;
+
+ 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>>());
+ 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__And_Vector128_Int64 testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector128_Int64 testClass)
+ {
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Int64*)(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<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+ private static Int64[] _data2 = new Int64[Op2ElementCount];
+
+ private static Vector128<Int64> _clsVar1;
+ private static Vector128<Int64> _clsVar2;
+
+ private Vector128<Int64> _fld1;
+ private Vector128<Int64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_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>>());
+ 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__And_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 < 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.GetInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new Int64[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.And(
+ Unsafe.Read<Vector128<Int64>>(_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.And(
+ AdvSimd.LoadVector128((Int64*)(_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.And), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(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.And), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int64>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Int64*)(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<Vector128<Int64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector128((Int64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector128_Int64();
+ var result = AdvSimd.And(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__And_Vector128_Int64();
+
+ fixed (Vector128<Int64>* pFld1 = &test._fld1)
+ fixed (Vector128<Int64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Int64*)(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.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Int64*)(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.And(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.And(
+ AdvSimd.LoadVector128((Int64*)(&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(Vector128<Int64> op1, Vector128<Int64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[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<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<Int64>(Vector128<Int64>, 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 And_Vector128_SByte()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector128_SByte();
+
+ 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__And_Vector128_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector128<SByte> _fld1;
+ public Vector128<SByte> _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<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector128_SByte testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector128_SByte testClass)
+ {
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector128<SByte> _clsVar1;
+ private static Vector128<SByte> _clsVar2;
+
+ private Vector128<SByte> _fld1;
+ private Vector128<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector128_SByte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector128_SByte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.And(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.And(
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.And), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.And), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector128_SByte();
+ var result = AdvSimd.And(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__And_Vector128_SByte();
+
+ fixed (Vector128<SByte>* pFld1 = &test._fld1)
+ fixed (Vector128<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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.And(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.And(
+ AdvSimd.LoadVector128((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector128((SByte*)(&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(Vector128<SByte> op1, Vector128<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, 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];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ 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, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<SByte>(Vector128<SByte>, Vector128<SByte>): {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 And_Vector128_Single()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector128_Single();
+
+ 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__And_Vector128_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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 Vector128<Single> _fld1;
+ public Vector128<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector128_Single testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector128_Single testClass)
+ {
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector128_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector128_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.And(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_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.And(
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_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.And), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(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.And), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Single*)(pClsVar1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector128_Single();
+ var result = AdvSimd.And(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__And_Vector128_Single();
+
+ fixed (Vector128<Single>* pFld1 = &test._fld1)
+ fixed (Vector128<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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.And(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.And(
+ AdvSimd.LoadVector128((Single*)(&test._fld1)),
+ AdvSimd.LoadVector128((Single*)(&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(Vector128<Single> op1, Vector128<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.And(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<Single>(Vector128<Single>, Vector128<Single>): {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 And_Vector128_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__And_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__And_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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 Vector128<UInt16> _fld1;
+ public Vector128<UInt16> _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<Vector128<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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__And_Vector128_UInt16 testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector128_UInt16 testClass)
+ {
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector128<UInt16> _clsVar1;
+ private static Vector128<UInt16> _clsVar2;
+
+ private Vector128<UInt16> _fld1;
+ private Vector128<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_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>>());
+ 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__And_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 < 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.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.And(
+ Unsafe.Read<Vector128<UInt16>>(_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.And(
+ AdvSimd.LoadVector128((UInt16*)(_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.And), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt16>>(_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.And), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt16*)(_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.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector128((UInt16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector128_UInt16();
+ var result = AdvSimd.And(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__And_Vector128_UInt16();
+
+ fixed (Vector128<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((UInt16*)(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.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((UInt16*)(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.And(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.And(
+ AdvSimd.LoadVector128((UInt16*)(&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(Vector128<UInt16> op1, Vector128<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, 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];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<UInt16>(Vector128<UInt16>, 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 And_Vector128_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__And_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__And_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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 Vector128<UInt32> _fld1;
+ public Vector128<UInt32> _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<Vector128<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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__And_Vector128_UInt32 testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector128_UInt32 testClass)
+ {
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector128<UInt32> _clsVar1;
+ private static Vector128<UInt32> _clsVar2;
+
+ private Vector128<UInt32> _fld1;
+ private Vector128<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_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>>());
+ 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__And_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 < 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.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.And(
+ Unsafe.Read<Vector128<UInt32>>(_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.And(
+ AdvSimd.LoadVector128((UInt32*)(_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.And), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt32>>(_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.And), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt32*)(_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.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector128((UInt32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector128_UInt32();
+ var result = AdvSimd.And(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__And_Vector128_UInt32();
+
+ fixed (Vector128<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((UInt32*)(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.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((UInt32*)(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.And(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.And(
+ AdvSimd.LoadVector128((UInt32*)(&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(Vector128<UInt32> op1, Vector128<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, 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];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<UInt32>(Vector128<UInt32>, 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 And_Vector128_UInt64()
+ {
+ var test = new SimpleBinaryOpTest__And_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__And_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(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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<UInt64, 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 Vector128<UInt64> _fld1;
+ public Vector128<UInt64> _fld2;
+
+ 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>>());
+ 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__And_Vector128_UInt64 testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector128_UInt64 testClass)
+ {
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((UInt64*)(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<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+ private static UInt64[] _data2 = new UInt64[Op2ElementCount];
+
+ private static Vector128<UInt64> _clsVar1;
+ private static Vector128<UInt64> _clsVar2;
+
+ private Vector128<UInt64> _fld1;
+ private Vector128<UInt64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_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>>());
+ 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__And_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 < 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.GetUInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt64[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.And(
+ Unsafe.Read<Vector128<UInt64>>(_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.And(
+ AdvSimd.LoadVector128((UInt64*)(_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.And), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(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.And), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt64>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((UInt64*)(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<Vector128<UInt64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector128((UInt64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector128_UInt64();
+ var result = AdvSimd.And(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__And_Vector128_UInt64();
+
+ fixed (Vector128<UInt64>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((UInt64*)(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.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector128((UInt64*)(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.And(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.And(
+ AdvSimd.LoadVector128((UInt64*)(&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(Vector128<UInt64> op1, Vector128<UInt64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[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<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<UInt64>(Vector128<UInt64>, 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 And_Vector64_Byte()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector64_Byte();
+
+ 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__And_Vector64_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector64<Byte> _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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector64_Byte testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector64_Byte testClass)
+ {
+ fixed (Vector64<Byte>* pFld1 = &_fld1)
+ fixed (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector64<Byte> _clsVar1;
+ private static Vector64<Byte> _clsVar2;
+
+ private Vector64<Byte> _fld1;
+ private Vector64<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.And(
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_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.And(
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_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.And), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.And), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _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 (Vector64<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector64((Byte*)(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<Vector64<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector64((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector64_Byte();
+ var result = AdvSimd.And(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__And_Vector64_Byte();
+
+ fixed (Vector64<Byte>* pFld1 = &test._fld1)
+ fixed (Vector64<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.And(_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 (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(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.And(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.And(
+ AdvSimd.LoadVector64((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector64((Byte*)(&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, Vector64<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[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<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<Byte>(Vector64<Byte>, Vector64<Byte>): {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 And_Vector64_Double()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector64_Double();
+
+ 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__And_Vector64_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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<Double> _fld1;
+ public Vector64<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector64_Double testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector64_Double testClass)
+ {
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector64<Double> _clsVar1;
+ private static Vector64<Double> _clsVar2;
+
+ private Vector64<Double> _fld1;
+ private Vector64<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector64_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector64_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[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.And(
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_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.And(
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_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.And), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(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.And), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Double*)(pClsVar1)),
+ AdvSimd.LoadVector64((Double*)(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<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector64_Double();
+ var result = AdvSimd.And(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__And_Vector64_Double();
+
+ fixed (Vector64<Double>* pFld1 = &test._fld1)
+ fixed (Vector64<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(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.And(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.And(
+ AdvSimd.LoadVector64((Double*)(&test._fld1)),
+ AdvSimd.LoadVector64((Double*)(&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<Double> op1, Vector64<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.And(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<Double>(Vector64<Double>, Vector64<Double>): {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 And_Vector64_Int16()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector64_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__And_Vector64_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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<Int16> _fld1;
+ public Vector64<Int16> _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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector64_Int16 testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector64_Int16 testClass)
+ {
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ fixed (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((Int16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector64<Int16> _clsVar1;
+ private static Vector64<Int16> _clsVar2;
+
+ private Vector64<Int16> _fld1;
+ private Vector64<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.And(
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.And(
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.And), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.And), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _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 (Vector64<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Int16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector64((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector64_Int16();
+ var result = AdvSimd.And(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__And_Vector64_Int16();
+
+ fixed (Vector64<Int16>* pFld1 = &test._fld1)
+ fixed (Vector64<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.And(_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 (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.And(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.And(
+ AdvSimd.LoadVector64((Int16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int16> op1, Vector64<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<Int16>(Vector64<Int16>, Vector64<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 And_Vector64_Int32()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector64_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__And_Vector64_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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<Int32> _fld1;
+ public Vector64<Int32> _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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref testStruct._fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector64_Int32 testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector64_Int32 testClass)
+ {
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ fixed (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((Int32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector64<Int32> _clsVar1;
+ private static Vector64<Int32> _clsVar2;
+
+ private Vector64<Int32> _fld1;
+ private Vector64<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.And(
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.And(
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.And), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.And), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _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 (Vector64<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Int32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector64((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector64_Int32();
+ var result = AdvSimd.And(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__And_Vector64_Int32();
+
+ fixed (Vector64<Int32>* pFld1 = &test._fld1)
+ fixed (Vector64<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.And(_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 (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.And(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.And(
+ AdvSimd.LoadVector64((Int32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int32> op1, Vector64<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<Int32>(Vector64<Int32>, Vector64<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 And_Vector64_Int64()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector64_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__And_Vector64_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(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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<Int64, 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<Int64> _fld1;
+ public Vector64<Int64> _fld2;
+
+ 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<Vector64<Int64>, byte>(ref testStruct._fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref testStruct._fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector64_Int64 testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector64_Int64 testClass)
+ {
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ fixed (Vector64<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((Int64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+ private static Int64[] _data2 = new Int64[Op2ElementCount];
+
+ private static Vector64<Int64> _clsVar1;
+ private static Vector64<Int64> _clsVar2;
+
+ private Vector64<Int64> _fld1;
+ private Vector64<Int64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector64_Int64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector64_Int64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new Int64[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.And(
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.And(
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.And), new Type[] { typeof(Vector64<Int64>), typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(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.And), new Type[] { typeof(Vector64<Int64>), typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int64>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Int64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Int64*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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((Int64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector64_Int64();
+ var result = AdvSimd.And(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__And_Vector64_Int64();
+
+ fixed (Vector64<Int64>* pFld1 = &test._fld1)
+ fixed (Vector64<Int64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((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.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ fixed (Vector64<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((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.And(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.And(
+ AdvSimd.LoadVector64((Int64*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int64> op1, Vector64<Int64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<Int64>(Vector64<Int64>, Vector64<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 And_Vector64_SByte()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector64_SByte();
+
+ 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__And_Vector64_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector64<SByte> _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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector64_SByte testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector64_SByte testClass)
+ {
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ fixed (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector64<SByte> _clsVar1;
+ private static Vector64<SByte> _clsVar2;
+
+ private Vector64<SByte> _fld1;
+ private Vector64<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.And(
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_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.And(
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_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.And), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.And), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _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 (Vector64<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector64((SByte*)(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<Vector64<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector64((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector64_SByte();
+ var result = AdvSimd.And(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__And_Vector64_SByte();
+
+ fixed (Vector64<SByte>* pFld1 = &test._fld1)
+ fixed (Vector64<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.And(_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 (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(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.And(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.And(
+ AdvSimd.LoadVector64((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector64((SByte*)(&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, Vector64<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[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<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<SByte>(Vector64<SByte>, Vector64<SByte>): {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 And_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector64_Single();
+
+ 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__And_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector64_Single testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.And(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.And(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.And), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(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.And), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector64_Single();
+ var result = AdvSimd.And(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__And_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.And(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.And(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.And(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<Single>(Vector64<Single>, Vector64<Single>): {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 And_Vector64_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector64_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__And_Vector64_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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<UInt16> _fld1;
+ public Vector64<UInt16> _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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector64_UInt16 testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector64_UInt16 testClass)
+ {
+ fixed (Vector64<UInt16>* pFld1 = &_fld1)
+ fixed (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((UInt16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector64<UInt16> _clsVar1;
+ private static Vector64<UInt16> _clsVar2;
+
+ private Vector64<UInt16> _fld1;
+ private Vector64<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _clsVar2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.And(
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.And(
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.And), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.And), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _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 (Vector64<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((UInt16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector64((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector64_UInt16();
+ var result = AdvSimd.And(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__And_Vector64_UInt16();
+
+ fixed (Vector64<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.And(_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 (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.And(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.And(
+ AdvSimd.LoadVector64((UInt16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt16> op1, Vector64<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] left, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<UInt16>(Vector64<UInt16>, Vector64<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 And_Vector64_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector64_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__And_Vector64_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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<UInt32> _fld1;
+ public Vector64<UInt32> _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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector64_UInt32 testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector64_UInt32 testClass)
+ {
+ fixed (Vector64<UInt32>* pFld1 = &_fld1)
+ fixed (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((UInt32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector64<UInt32> _clsVar1;
+ private static Vector64<UInt32> _clsVar2;
+
+ private Vector64<UInt32> _fld1;
+ private Vector64<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _clsVar2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.And(
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.And(
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.And), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.And), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _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 (Vector64<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((UInt32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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.LoadVector64((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector64_UInt32();
+ var result = AdvSimd.And(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__And_Vector64_UInt32();
+
+ fixed (Vector64<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.And(_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 (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.And(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.And(
+ AdvSimd.LoadVector64((UInt32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt32> op1, Vector64<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] left, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<UInt32>(Vector64<UInt32>, Vector64<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 And_Vector64_UInt64()
+ {
+ var test = new SimpleBinaryOpTest__And_Vector64_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__And_Vector64_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(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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<UInt64, 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<UInt64> _fld1;
+ public Vector64<UInt64> _fld2;
+
+ 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<Vector64<UInt64>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__And_Vector64_UInt64 testClass)
+ {
+ var result = AdvSimd.And(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__And_Vector64_UInt64 testClass)
+ {
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ fixed (Vector64<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((UInt64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+ private static UInt64[] _data2 = new UInt64[Op2ElementCount];
+
+ private static Vector64<UInt64> _clsVar1;
+ private static Vector64<UInt64> _clsVar2;
+
+ private Vector64<UInt64> _fld1;
+ private Vector64<UInt64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__And_Vector64_UInt64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _clsVar1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _clsVar2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ }
+
+ public SimpleBinaryOpTest__And_Vector64_UInt64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt64[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.And(
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.And(
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.And), new Type[] { typeof(Vector64<UInt64>), typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(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.And), new Type[] { typeof(Vector64<UInt64>), typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.And(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<UInt64>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<UInt64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((UInt64*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.And(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((UInt64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.And(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__And_Vector64_UInt64();
+ var result = AdvSimd.And(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__And_Vector64_UInt64();
+
+ fixed (Vector64<UInt64>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((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.And(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ fixed (Vector64<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.And(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((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.And(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.And(
+ AdvSimd.LoadVector64((UInt64*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt64> op1, Vector64<UInt64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.And(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.And)}<UInt64>(Vector64<UInt64>, Vector64<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 BitwiseClear_Vector128_Byte()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_Byte();
+
+ 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__BitwiseClear_Vector128_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector128<Byte> _fld1;
+ public Vector128<Byte> _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<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector128_Byte testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector128_Byte testClass)
+ {
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector128<Byte> _clsVar1;
+ private static Vector128<Byte> _clsVar2;
+
+ private Vector128<Byte> _fld1;
+ private Vector128<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector128_Byte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector128_Byte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.BitwiseClear(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.BitwiseClear(
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.BitwiseClear), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.BitwiseClear), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Byte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector128((Byte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_Byte();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector128_Byte();
+
+ fixed (Vector128<Byte>* pFld1 = &test._fld1)
+ fixed (Vector128<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector128((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector128((Byte*)(&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(Vector128<Byte> op1, Vector128<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, 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];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ 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, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<Byte>(Vector128<Byte>, Vector128<Byte>): {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 BitwiseClear_Vector128_Double()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_Double();
+
+ 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__BitwiseClear_Vector128_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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 Vector128<Double> _fld1;
+ public Vector128<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector128_Double testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector128_Double testClass)
+ {
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+ private static Vector128<Double> _clsVar2;
+
+ private Vector128<Double> _fld1;
+ private Vector128<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector128_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector128_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[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.BitwiseClear(
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_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.BitwiseClear(
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_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.BitwiseClear), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(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.BitwiseClear), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Double*)(pClsVar1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_Double();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector128_Double();
+
+ fixed (Vector128<Double>* pFld1 = &test._fld1)
+ fixed (Vector128<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector128((Double*)(&test._fld1)),
+ AdvSimd.LoadVector128((Double*)(&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(Vector128<Double> op1, Vector128<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<Double>(Vector128<Double>, Vector128<Double>): {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 BitwiseClear_Vector128_Int16()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_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__BitwiseClear_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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 Vector128<Int16> _fld1;
+ public Vector128<Int16> _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<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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__BitwiseClear_Vector128_Int16 testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector128_Int16 testClass)
+ {
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector128<Int16> _clsVar1;
+ private static Vector128<Int16> _clsVar2;
+
+ private Vector128<Int16> _fld1;
+ private Vector128<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_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>>());
+ 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__BitwiseClear_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 < 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.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.BitwiseClear(
+ Unsafe.Read<Vector128<Int16>>(_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.BitwiseClear(
+ AdvSimd.LoadVector128((Int16*)(_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.BitwiseClear), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int16>>(_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.BitwiseClear), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int16*)(_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.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector128((Int16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_Int16();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector128_Int16();
+
+ fixed (Vector128<Int16>* pFld1 = &test._fld1)
+ fixed (Vector128<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Int16*)(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.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Int16*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector128((Int16*)(&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(Vector128<Int16> op1, Vector128<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, 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];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<Int16>(Vector128<Int16>, 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 BitwiseClear_Vector128_Int32()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_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__BitwiseClear_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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 Vector128<Int32> _fld1;
+ public Vector128<Int32> _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<Vector128<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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__BitwiseClear_Vector128_Int32 testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector128_Int32 testClass)
+ {
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector128<Int32> _clsVar1;
+ private static Vector128<Int32> _clsVar2;
+
+ private Vector128<Int32> _fld1;
+ private Vector128<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_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>>());
+ 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__BitwiseClear_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 < 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.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.BitwiseClear(
+ Unsafe.Read<Vector128<Int32>>(_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.BitwiseClear(
+ AdvSimd.LoadVector128((Int32*)(_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.BitwiseClear), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int32>>(_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.BitwiseClear), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int32*)(_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.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector128((Int32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_Int32();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector128_Int32();
+
+ fixed (Vector128<Int32>* pFld1 = &test._fld1)
+ fixed (Vector128<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Int32*)(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.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Int32*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector128((Int32*)(&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(Vector128<Int32> op1, Vector128<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, 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];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<Int32>(Vector128<Int32>, 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 BitwiseClear_Vector128_Int64()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_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__BitwiseClear_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(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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<Int64, 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 Vector128<Int64> _fld1;
+ public Vector128<Int64> _fld2;
+
+ 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>>());
+ 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__BitwiseClear_Vector128_Int64 testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector128_Int64 testClass)
+ {
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Int64*)(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<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+ private static Int64[] _data2 = new Int64[Op2ElementCount];
+
+ private static Vector128<Int64> _clsVar1;
+ private static Vector128<Int64> _clsVar2;
+
+ private Vector128<Int64> _fld1;
+ private Vector128<Int64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_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>>());
+ 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__BitwiseClear_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 < 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.GetInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new Int64[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.BitwiseClear(
+ Unsafe.Read<Vector128<Int64>>(_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.BitwiseClear(
+ AdvSimd.LoadVector128((Int64*)(_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.BitwiseClear), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(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.BitwiseClear), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int64>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Int64*)(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<Vector128<Int64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector128((Int64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_Int64();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector128_Int64();
+
+ fixed (Vector128<Int64>* pFld1 = &test._fld1)
+ fixed (Vector128<Int64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Int64*)(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.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Int64*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector128((Int64*)(&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(Vector128<Int64> op1, Vector128<Int64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[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<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<Int64>(Vector128<Int64>, 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 BitwiseClear_Vector128_SByte()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_SByte();
+
+ 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__BitwiseClear_Vector128_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector128<SByte> _fld1;
+ public Vector128<SByte> _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<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector128_SByte testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector128_SByte testClass)
+ {
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector128<SByte> _clsVar1;
+ private static Vector128<SByte> _clsVar2;
+
+ private Vector128<SByte> _fld1;
+ private Vector128<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector128_SByte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector128_SByte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.BitwiseClear(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.BitwiseClear(
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.BitwiseClear), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.BitwiseClear), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_SByte();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector128_SByte();
+
+ fixed (Vector128<SByte>* pFld1 = &test._fld1)
+ fixed (Vector128<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector128((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector128((SByte*)(&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(Vector128<SByte> op1, Vector128<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, 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];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ 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, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<SByte>(Vector128<SByte>, Vector128<SByte>): {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 BitwiseClear_Vector128_Single()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_Single();
+
+ 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__BitwiseClear_Vector128_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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 Vector128<Single> _fld1;
+ public Vector128<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector128_Single testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector128_Single testClass)
+ {
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector128_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector128_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.BitwiseClear(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_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.BitwiseClear(
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_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.BitwiseClear), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(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.BitwiseClear), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Single*)(pClsVar1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_Single();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector128_Single();
+
+ fixed (Vector128<Single>* pFld1 = &test._fld1)
+ fixed (Vector128<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector128((Single*)(&test._fld1)),
+ AdvSimd.LoadVector128((Single*)(&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(Vector128<Single> op1, Vector128<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<Single>(Vector128<Single>, Vector128<Single>): {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 BitwiseClear_Vector128_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_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__BitwiseClear_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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 Vector128<UInt16> _fld1;
+ public Vector128<UInt16> _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<Vector128<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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__BitwiseClear_Vector128_UInt16 testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector128_UInt16 testClass)
+ {
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector128<UInt16> _clsVar1;
+ private static Vector128<UInt16> _clsVar2;
+
+ private Vector128<UInt16> _fld1;
+ private Vector128<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_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>>());
+ 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__BitwiseClear_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 < 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.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.BitwiseClear(
+ Unsafe.Read<Vector128<UInt16>>(_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.BitwiseClear(
+ AdvSimd.LoadVector128((UInt16*)(_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.BitwiseClear), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt16>>(_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.BitwiseClear), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt16*)(_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.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector128((UInt16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_UInt16();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector128_UInt16();
+
+ fixed (Vector128<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((UInt16*)(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.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((UInt16*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector128((UInt16*)(&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(Vector128<UInt16> op1, Vector128<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, 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];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<UInt16>(Vector128<UInt16>, 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 BitwiseClear_Vector128_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_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__BitwiseClear_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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 Vector128<UInt32> _fld1;
+ public Vector128<UInt32> _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<Vector128<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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__BitwiseClear_Vector128_UInt32 testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector128_UInt32 testClass)
+ {
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector128<UInt32> _clsVar1;
+ private static Vector128<UInt32> _clsVar2;
+
+ private Vector128<UInt32> _fld1;
+ private Vector128<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_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>>());
+ 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__BitwiseClear_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 < 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.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.BitwiseClear(
+ Unsafe.Read<Vector128<UInt32>>(_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.BitwiseClear(
+ AdvSimd.LoadVector128((UInt32*)(_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.BitwiseClear), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt32>>(_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.BitwiseClear), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt32*)(_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.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector128((UInt32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_UInt32();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector128_UInt32();
+
+ fixed (Vector128<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((UInt32*)(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.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((UInt32*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector128((UInt32*)(&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(Vector128<UInt32> op1, Vector128<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, 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];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<UInt32>(Vector128<UInt32>, 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 BitwiseClear_Vector128_UInt64()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_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__BitwiseClear_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(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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<UInt64, 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 Vector128<UInt64> _fld1;
+ public Vector128<UInt64> _fld2;
+
+ 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>>());
+ 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__BitwiseClear_Vector128_UInt64 testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector128_UInt64 testClass)
+ {
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((UInt64*)(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<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+ private static UInt64[] _data2 = new UInt64[Op2ElementCount];
+
+ private static Vector128<UInt64> _clsVar1;
+ private static Vector128<UInt64> _clsVar2;
+
+ private Vector128<UInt64> _fld1;
+ private Vector128<UInt64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_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>>());
+ 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__BitwiseClear_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 < 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.GetUInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt64[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.BitwiseClear(
+ Unsafe.Read<Vector128<UInt64>>(_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.BitwiseClear(
+ AdvSimd.LoadVector128((UInt64*)(_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.BitwiseClear), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(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.BitwiseClear), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt64>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((UInt64*)(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<Vector128<UInt64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector128((UInt64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector128_UInt64();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector128_UInt64();
+
+ fixed (Vector128<UInt64>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((UInt64*)(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.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector128((UInt64*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector128((UInt64*)(&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(Vector128<UInt64> op1, Vector128<UInt64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[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<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<UInt64>(Vector128<UInt64>, 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 BitwiseClear_Vector64_Byte()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_Byte();
+
+ 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__BitwiseClear_Vector64_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector64<Byte> _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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector64_Byte testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector64_Byte testClass)
+ {
+ fixed (Vector64<Byte>* pFld1 = &_fld1)
+ fixed (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector64<Byte> _clsVar1;
+ private static Vector64<Byte> _clsVar2;
+
+ private Vector64<Byte> _fld1;
+ private Vector64<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.BitwiseClear(
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_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.BitwiseClear(
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_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.BitwiseClear), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.BitwiseClear), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _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 (Vector64<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector64((Byte*)(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<Vector64<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector64((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_Byte();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector64_Byte();
+
+ fixed (Vector64<Byte>* pFld1 = &test._fld1)
+ fixed (Vector64<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.BitwiseClear(_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 (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector64((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector64((Byte*)(&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, Vector64<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[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<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<Byte>(Vector64<Byte>, Vector64<Byte>): {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 BitwiseClear_Vector64_Double()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_Double();
+
+ 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__BitwiseClear_Vector64_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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<Double> _fld1;
+ public Vector64<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector64_Double testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector64_Double testClass)
+ {
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector64<Double> _clsVar1;
+ private static Vector64<Double> _clsVar2;
+
+ private Vector64<Double> _fld1;
+ private Vector64<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector64_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector64_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[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.BitwiseClear(
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_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.BitwiseClear(
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_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.BitwiseClear), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(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.BitwiseClear), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Double*)(pClsVar1)),
+ AdvSimd.LoadVector64((Double*)(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<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_Double();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector64_Double();
+
+ fixed (Vector64<Double>* pFld1 = &test._fld1)
+ fixed (Vector64<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector64((Double*)(&test._fld1)),
+ AdvSimd.LoadVector64((Double*)(&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<Double> op1, Vector64<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<Double>(Vector64<Double>, Vector64<Double>): {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 BitwiseClear_Vector64_Int16()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_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__BitwiseClear_Vector64_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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<Int16> _fld1;
+ public Vector64<Int16> _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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector64_Int16 testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector64_Int16 testClass)
+ {
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ fixed (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((Int16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector64<Int16> _clsVar1;
+ private static Vector64<Int16> _clsVar2;
+
+ private Vector64<Int16> _fld1;
+ private Vector64<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.BitwiseClear(
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.BitwiseClear(
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.BitwiseClear), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.BitwiseClear), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _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 (Vector64<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Int16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector64((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_Int16();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector64_Int16();
+
+ fixed (Vector64<Int16>* pFld1 = &test._fld1)
+ fixed (Vector64<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.BitwiseClear(_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 (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector64((Int16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int16> op1, Vector64<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<Int16>(Vector64<Int16>, Vector64<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 BitwiseClear_Vector64_Int32()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_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__BitwiseClear_Vector64_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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<Int32> _fld1;
+ public Vector64<Int32> _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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref testStruct._fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector64_Int32 testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector64_Int32 testClass)
+ {
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ fixed (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((Int32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector64<Int32> _clsVar1;
+ private static Vector64<Int32> _clsVar2;
+
+ private Vector64<Int32> _fld1;
+ private Vector64<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.BitwiseClear(
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.BitwiseClear(
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.BitwiseClear), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.BitwiseClear), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _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 (Vector64<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Int32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector64((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_Int32();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector64_Int32();
+
+ fixed (Vector64<Int32>* pFld1 = &test._fld1)
+ fixed (Vector64<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.BitwiseClear(_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 (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector64((Int32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int32> op1, Vector64<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<Int32>(Vector64<Int32>, Vector64<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 BitwiseClear_Vector64_Int64()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_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__BitwiseClear_Vector64_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(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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<Int64, 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<Int64> _fld1;
+ public Vector64<Int64> _fld2;
+
+ 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<Vector64<Int64>, byte>(ref testStruct._fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref testStruct._fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector64_Int64 testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector64_Int64 testClass)
+ {
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ fixed (Vector64<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((Int64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+ private static Int64[] _data2 = new Int64[Op2ElementCount];
+
+ private static Vector64<Int64> _clsVar1;
+ private static Vector64<Int64> _clsVar2;
+
+ private Vector64<Int64> _fld1;
+ private Vector64<Int64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector64_Int64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector64_Int64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new Int64[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.BitwiseClear(
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.BitwiseClear(
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.BitwiseClear), new Type[] { typeof(Vector64<Int64>), typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(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.BitwiseClear), new Type[] { typeof(Vector64<Int64>), typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int64>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Int64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Int64*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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((Int64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_Int64();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector64_Int64();
+
+ fixed (Vector64<Int64>* pFld1 = &test._fld1)
+ fixed (Vector64<Int64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((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.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ fixed (Vector64<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector64((Int64*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int64> op1, Vector64<Int64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<Int64>(Vector64<Int64>, Vector64<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 BitwiseClear_Vector64_SByte()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_SByte();
+
+ 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__BitwiseClear_Vector64_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector64<SByte> _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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector64_SByte testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector64_SByte testClass)
+ {
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ fixed (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector64<SByte> _clsVar1;
+ private static Vector64<SByte> _clsVar2;
+
+ private Vector64<SByte> _fld1;
+ private Vector64<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.BitwiseClear(
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_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.BitwiseClear(
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_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.BitwiseClear), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.BitwiseClear), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _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 (Vector64<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector64((SByte*)(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<Vector64<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector64((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_SByte();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector64_SByte();
+
+ fixed (Vector64<SByte>* pFld1 = &test._fld1)
+ fixed (Vector64<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.BitwiseClear(_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 (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector64((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector64((SByte*)(&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, Vector64<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[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<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<SByte>(Vector64<SByte>, Vector64<SByte>): {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 BitwiseClear_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_Single();
+
+ 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__BitwiseClear_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector64_Single testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.BitwiseClear(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.BitwiseClear(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.BitwiseClear), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(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.BitwiseClear), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_Single();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<Single>(Vector64<Single>, Vector64<Single>): {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 BitwiseClear_Vector64_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_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__BitwiseClear_Vector64_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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<UInt16> _fld1;
+ public Vector64<UInt16> _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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector64_UInt16 testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector64_UInt16 testClass)
+ {
+ fixed (Vector64<UInt16>* pFld1 = &_fld1)
+ fixed (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((UInt16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector64<UInt16> _clsVar1;
+ private static Vector64<UInt16> _clsVar2;
+
+ private Vector64<UInt16> _fld1;
+ private Vector64<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _clsVar2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.BitwiseClear(
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.BitwiseClear(
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.BitwiseClear), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.BitwiseClear), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _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 (Vector64<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((UInt16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector64((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_UInt16();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector64_UInt16();
+
+ fixed (Vector64<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.BitwiseClear(_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 (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector64((UInt16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt16> op1, Vector64<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] left, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<UInt16>(Vector64<UInt16>, Vector64<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 BitwiseClear_Vector64_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_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__BitwiseClear_Vector64_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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<UInt32> _fld1;
+ public Vector64<UInt32> _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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector64_UInt32 testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector64_UInt32 testClass)
+ {
+ fixed (Vector64<UInt32>* pFld1 = &_fld1)
+ fixed (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((UInt32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector64<UInt32> _clsVar1;
+ private static Vector64<UInt32> _clsVar2;
+
+ private Vector64<UInt32> _fld1;
+ private Vector64<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _clsVar2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.BitwiseClear(
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.BitwiseClear(
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.BitwiseClear), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.BitwiseClear), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _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 (Vector64<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((UInt32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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.LoadVector64((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_UInt32();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector64_UInt32();
+
+ fixed (Vector64<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.BitwiseClear(_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 (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector64((UInt32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt32> op1, Vector64<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] left, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<UInt32>(Vector64<UInt32>, Vector64<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 BitwiseClear_Vector64_UInt64()
+ {
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_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__BitwiseClear_Vector64_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(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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<UInt64, 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<UInt64> _fld1;
+ public Vector64<UInt64> _fld2;
+
+ 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<Vector64<UInt64>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__BitwiseClear_Vector64_UInt64 testClass)
+ {
+ var result = AdvSimd.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__BitwiseClear_Vector64_UInt64 testClass)
+ {
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ fixed (Vector64<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((UInt64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+ private static UInt64[] _data2 = new UInt64[Op2ElementCount];
+
+ private static Vector64<UInt64> _clsVar1;
+ private static Vector64<UInt64> _clsVar2;
+
+ private Vector64<UInt64> _fld1;
+ private Vector64<UInt64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__BitwiseClear_Vector64_UInt64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _clsVar1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _clsVar2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ }
+
+ public SimpleBinaryOpTest__BitwiseClear_Vector64_UInt64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt64[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.BitwiseClear(
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.BitwiseClear(
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.BitwiseClear), new Type[] { typeof(Vector64<UInt64>), typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(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.BitwiseClear), new Type[] { typeof(Vector64<UInt64>), typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.BitwiseClear(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<UInt64>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<UInt64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((UInt64*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.BitwiseClear(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((UInt64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.BitwiseClear(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__BitwiseClear_Vector64_UInt64();
+ var result = AdvSimd.BitwiseClear(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__BitwiseClear_Vector64_UInt64();
+
+ fixed (Vector64<UInt64>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((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.BitwiseClear(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ fixed (Vector64<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.BitwiseClear(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((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.BitwiseClear(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.BitwiseClear(
+ AdvSimd.LoadVector64((UInt64*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt64> op1, Vector64<UInt64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.BitwiseClear(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.BitwiseClear)}<UInt64>(Vector64<UInt64>, Vector64<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 DivideScalar_Vector64_Double()
+ {
+ var test = new SimpleBinaryOpTest__DivideScalar_Vector64_Double();
+
+ 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__DivideScalar_Vector64_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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<Double> _fld1;
+ public Vector64<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__DivideScalar_Vector64_Double testClass)
+ {
+ var result = AdvSimd.DivideScalar(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__DivideScalar_Vector64_Double testClass)
+ {
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.DivideScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector64<Double> _clsVar1;
+ private static Vector64<Double> _clsVar2;
+
+ private Vector64<Double> _fld1;
+ private Vector64<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__DivideScalar_Vector64_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ }
+
+ public SimpleBinaryOpTest__DivideScalar_Vector64_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[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.DivideScalar(
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_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.DivideScalar(
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_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.DivideScalar), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(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.DivideScalar), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.DivideScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.DivideScalar(
+ AdvSimd.LoadVector64((Double*)(pClsVar1)),
+ AdvSimd.LoadVector64((Double*)(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<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.DivideScalar(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((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.DivideScalar(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__DivideScalar_Vector64_Double();
+ var result = AdvSimd.DivideScalar(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__DivideScalar_Vector64_Double();
+
+ fixed (Vector64<Double>* pFld1 = &test._fld1)
+ fixed (Vector64<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.DivideScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.DivideScalar(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.DivideScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(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.DivideScalar(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.DivideScalar(
+ AdvSimd.LoadVector64((Double*)(&test._fld1)),
+ AdvSimd.LoadVector64((Double*)(&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<Double> op1, Vector64<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(Helpers.Divide(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DivideScalar)}<Double>(Vector64<Double>, Vector64<Double>): {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 DivideScalar_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__DivideScalar_Vector64_Single();
+
+ 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__DivideScalar_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__DivideScalar_Vector64_Single testClass)
+ {
+ var result = AdvSimd.DivideScalar(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__DivideScalar_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.DivideScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__DivideScalar_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__DivideScalar_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.DivideScalar(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.DivideScalar(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.DivideScalar), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(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.DivideScalar), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.DivideScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.DivideScalar(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.DivideScalar(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.DivideScalar(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__DivideScalar_Vector64_Single();
+ var result = AdvSimd.DivideScalar(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__DivideScalar_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.DivideScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.DivideScalar(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.DivideScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.DivideScalar(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.DivideScalar(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(Helpers.Divide(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.DivideScalar)}<Single>(Vector64<Single>, Vector64<Single>): {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 Max_Vector128_Byte()
+ {
+ var test = new SimpleBinaryOpTest__Max_Vector128_Byte();
+
+ 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__Max_Vector128_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector128<Byte> _fld1;
+ public Vector128<Byte> _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<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Max_Vector128_Byte testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector128_Byte testClass)
+ {
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector128<Byte> _clsVar1;
+ private static Vector128<Byte> _clsVar2;
+
+ private Vector128<Byte> _fld1;
+ private Vector128<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_Vector128_Byte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__Max_Vector128_Byte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.Max(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.Max(
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.Max), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.Max), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.Max(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Byte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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.LoadVector128((Byte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector128_Byte();
+ var result = AdvSimd.Max(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__Max_Vector128_Byte();
+
+ fixed (Vector128<Byte>* pFld1 = &test._fld1)
+ fixed (Vector128<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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.Max(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.Max(
+ AdvSimd.LoadVector128((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector128((Byte*)(&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(Vector128<Byte> op1, Vector128<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, 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];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ 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, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Max(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<Byte>(Vector128<Byte>, Vector128<Byte>): {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 Max_Vector128_Int16()
+ {
+ var test = new SimpleBinaryOpTest__Max_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__Max_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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 Vector128<Int16> _fld1;
+ public Vector128<Int16> _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<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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__Max_Vector128_Int16 testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector128_Int16 testClass)
+ {
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector128<Int16> _clsVar1;
+ private static Vector128<Int16> _clsVar2;
+
+ private Vector128<Int16> _fld1;
+ private Vector128<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_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>>());
+ 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__Max_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 < 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.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Max(
+ Unsafe.Read<Vector128<Int16>>(_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.Max(
+ AdvSimd.LoadVector128((Int16*)(_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.Max), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int16>>(_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.Max), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int16*)(_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.Max(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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.LoadVector128((Int16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector128_Int16();
+ var result = AdvSimd.Max(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__Max_Vector128_Int16();
+
+ fixed (Vector128<Int16>* pFld1 = &test._fld1)
+ fixed (Vector128<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Int16*)(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.Max(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Int16*)(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.Max(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.Max(
+ AdvSimd.LoadVector128((Int16*)(&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(Vector128<Int16> op1, Vector128<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, 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];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Max(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<Int16>(Vector128<Int16>, 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 Max_Vector128_Int32()
+ {
+ var test = new SimpleBinaryOpTest__Max_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__Max_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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 Vector128<Int32> _fld1;
+ public Vector128<Int32> _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<Vector128<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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__Max_Vector128_Int32 testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector128_Int32 testClass)
+ {
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector128<Int32> _clsVar1;
+ private static Vector128<Int32> _clsVar2;
+
+ private Vector128<Int32> _fld1;
+ private Vector128<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_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>>());
+ 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__Max_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 < 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.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Max(
+ Unsafe.Read<Vector128<Int32>>(_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.Max(
+ AdvSimd.LoadVector128((Int32*)(_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.Max), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int32>>(_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.Max), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int32*)(_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.Max(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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.LoadVector128((Int32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector128_Int32();
+ var result = AdvSimd.Max(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__Max_Vector128_Int32();
+
+ fixed (Vector128<Int32>* pFld1 = &test._fld1)
+ fixed (Vector128<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Int32*)(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.Max(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Int32*)(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.Max(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.Max(
+ AdvSimd.LoadVector128((Int32*)(&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(Vector128<Int32> op1, Vector128<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, 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];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Max(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<Int32>(Vector128<Int32>, 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 Max_Vector128_SByte()
+ {
+ var test = new SimpleBinaryOpTest__Max_Vector128_SByte();
+
+ 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__Max_Vector128_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector128<SByte> _fld1;
+ public Vector128<SByte> _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<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Max_Vector128_SByte testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector128_SByte testClass)
+ {
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector128<SByte> _clsVar1;
+ private static Vector128<SByte> _clsVar2;
+
+ private Vector128<SByte> _fld1;
+ private Vector128<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_Vector128_SByte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__Max_Vector128_SByte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Max(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.Max(
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.Max), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.Max), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.Max(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector128_SByte();
+ var result = AdvSimd.Max(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__Max_Vector128_SByte();
+
+ fixed (Vector128<SByte>* pFld1 = &test._fld1)
+ fixed (Vector128<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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.Max(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.Max(
+ AdvSimd.LoadVector128((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector128((SByte*)(&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(Vector128<SByte> op1, Vector128<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, 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];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ 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, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Max(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<SByte>(Vector128<SByte>, Vector128<SByte>): {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 Max_Vector128_Single()
+ {
+ var test = new SimpleBinaryOpTest__Max_Vector128_Single();
+
+ 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__Max_Vector128_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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 Vector128<Single> _fld1;
+ public Vector128<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Max_Vector128_Single testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector128_Single testClass)
+ {
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_Vector128_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Max_Vector128_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.Max(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_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.Max(
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_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.Max), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(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.Max), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Max(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Single*)(pClsVar1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector128_Single();
+ var result = AdvSimd.Max(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__Max_Vector128_Single();
+
+ fixed (Vector128<Single>* pFld1 = &test._fld1)
+ fixed (Vector128<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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.Max(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.Max(
+ AdvSimd.LoadVector128((Single*)(&test._fld1)),
+ AdvSimd.LoadVector128((Single*)(&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(Vector128<Single> op1, Vector128<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Max(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<Single>(Vector128<Single>, Vector128<Single>): {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 Max_Vector128_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__Max_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__Max_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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 Vector128<UInt16> _fld1;
+ public Vector128<UInt16> _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<Vector128<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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__Max_Vector128_UInt16 testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector128_UInt16 testClass)
+ {
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector128<UInt16> _clsVar1;
+ private static Vector128<UInt16> _clsVar2;
+
+ private Vector128<UInt16> _fld1;
+ private Vector128<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_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>>());
+ 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__Max_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 < 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.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.Max(
+ Unsafe.Read<Vector128<UInt16>>(_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.Max(
+ AdvSimd.LoadVector128((UInt16*)(_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.Max), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt16>>(_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.Max), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt16*)(_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.Max(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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.LoadVector128((UInt16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector128_UInt16();
+ var result = AdvSimd.Max(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__Max_Vector128_UInt16();
+
+ fixed (Vector128<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((UInt16*)(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.Max(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((UInt16*)(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.Max(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.Max(
+ AdvSimd.LoadVector128((UInt16*)(&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(Vector128<UInt16> op1, Vector128<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, 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];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Max(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<UInt16>(Vector128<UInt16>, 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 Max_Vector128_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__Max_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__Max_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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 Vector128<UInt32> _fld1;
+ public Vector128<UInt32> _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<Vector128<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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__Max_Vector128_UInt32 testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector128_UInt32 testClass)
+ {
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector128<UInt32> _clsVar1;
+ private static Vector128<UInt32> _clsVar2;
+
+ private Vector128<UInt32> _fld1;
+ private Vector128<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_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>>());
+ 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__Max_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 < 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.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.Max(
+ Unsafe.Read<Vector128<UInt32>>(_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.Max(
+ AdvSimd.LoadVector128((UInt32*)(_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.Max), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt32>>(_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.Max), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt32*)(_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.Max(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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.LoadVector128((UInt32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector128_UInt32();
+ var result = AdvSimd.Max(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__Max_Vector128_UInt32();
+
+ fixed (Vector128<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((UInt32*)(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.Max(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector128((UInt32*)(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.Max(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.Max(
+ AdvSimd.LoadVector128((UInt32*)(&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(Vector128<UInt32> op1, Vector128<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, 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];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Max(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<UInt32>(Vector128<UInt32>, 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 Max_Vector64_Byte()
+ {
+ var test = new SimpleBinaryOpTest__Max_Vector64_Byte();
+
+ 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__Max_Vector64_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector64<Byte> _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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Max_Vector64_Byte testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector64_Byte testClass)
+ {
+ fixed (Vector64<Byte>* pFld1 = &_fld1)
+ fixed (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector64<Byte> _clsVar1;
+ private static Vector64<Byte> _clsVar2;
+
+ private Vector64<Byte> _fld1;
+ private Vector64<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__Max_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.Max(
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_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.Max(
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_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.Max), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Max), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Max(
+ _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 (Vector64<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector64((Byte*)(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<Vector64<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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.LoadVector64((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector64_Byte();
+ var result = AdvSimd.Max(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__Max_Vector64_Byte();
+
+ fixed (Vector64<Byte>* pFld1 = &test._fld1)
+ fixed (Vector64<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Max(_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 (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(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.Max(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.Max(
+ AdvSimd.LoadVector64((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector64((Byte*)(&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, Vector64<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[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<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Max(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<Byte>(Vector64<Byte>, Vector64<Byte>): {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 Max_Vector64_Int16()
+ {
+ var test = new SimpleBinaryOpTest__Max_Vector64_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__Max_Vector64_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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<Int16> _fld1;
+ public Vector64<Int16> _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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Max_Vector64_Int16 testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector64_Int16 testClass)
+ {
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ fixed (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((Int16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector64<Int16> _clsVar1;
+ private static Vector64<Int16> _clsVar2;
+
+ private Vector64<Int16> _fld1;
+ private Vector64<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ }
+
+ public SimpleBinaryOpTest__Max_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Max(
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Max(
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Max), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Max), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Max(
+ _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 (Vector64<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Int16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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.LoadVector64((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector64_Int16();
+ var result = AdvSimd.Max(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__Max_Vector64_Int16();
+
+ fixed (Vector64<Int16>* pFld1 = &test._fld1)
+ fixed (Vector64<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Max(_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 (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Max(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.Max(
+ AdvSimd.LoadVector64((Int16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int16> op1, Vector64<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Max(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<Int16>(Vector64<Int16>, Vector64<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 Max_Vector64_Int32()
+ {
+ var test = new SimpleBinaryOpTest__Max_Vector64_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__Max_Vector64_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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<Int32> _fld1;
+ public Vector64<Int32> _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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref testStruct._fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Max_Vector64_Int32 testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector64_Int32 testClass)
+ {
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ fixed (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((Int32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector64<Int32> _clsVar1;
+ private static Vector64<Int32> _clsVar2;
+
+ private Vector64<Int32> _fld1;
+ private Vector64<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ }
+
+ public SimpleBinaryOpTest__Max_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Max(
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Max(
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Max), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Max), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Max(
+ _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 (Vector64<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Int32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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.LoadVector64((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector64_Int32();
+ var result = AdvSimd.Max(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__Max_Vector64_Int32();
+
+ fixed (Vector64<Int32>* pFld1 = &test._fld1)
+ fixed (Vector64<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Max(_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 (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Max(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.Max(
+ AdvSimd.LoadVector64((Int32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int32> op1, Vector64<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Max(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<Int32>(Vector64<Int32>, Vector64<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 Max_Vector64_SByte()
+ {
+ var test = new SimpleBinaryOpTest__Max_Vector64_SByte();
+
+ 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__Max_Vector64_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector64<SByte> _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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Max_Vector64_SByte testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector64_SByte testClass)
+ {
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ fixed (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector64<SByte> _clsVar1;
+ private static Vector64<SByte> _clsVar2;
+
+ private Vector64<SByte> _fld1;
+ private Vector64<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__Max_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Max(
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_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.Max(
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_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.Max), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Max), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Max(
+ _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 (Vector64<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector64((SByte*)(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<Vector64<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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.LoadVector64((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector64_SByte();
+ var result = AdvSimd.Max(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__Max_Vector64_SByte();
+
+ fixed (Vector64<SByte>* pFld1 = &test._fld1)
+ fixed (Vector64<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Max(_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 (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(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.Max(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.Max(
+ AdvSimd.LoadVector64((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector64((SByte*)(&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, Vector64<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[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<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Max(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<SByte>(Vector64<SByte>, Vector64<SByte>): {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 Max_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__Max_Vector64_Single();
+
+ 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__Max_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Max_Vector64_Single testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Max_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.Max(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.Max(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.Max), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(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.Max), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Max(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector64_Single();
+ var result = AdvSimd.Max(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__Max_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.Max(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.Max(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Max(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<Single>(Vector64<Single>, Vector64<Single>): {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 Max_Vector64_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__Max_Vector64_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__Max_Vector64_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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<UInt16> _fld1;
+ public Vector64<UInt16> _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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Max_Vector64_UInt16 testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector64_UInt16 testClass)
+ {
+ fixed (Vector64<UInt16>* pFld1 = &_fld1)
+ fixed (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((UInt16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector64<UInt16> _clsVar1;
+ private static Vector64<UInt16> _clsVar2;
+
+ private Vector64<UInt16> _fld1;
+ private Vector64<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _clsVar2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ }
+
+ public SimpleBinaryOpTest__Max_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.Max(
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Max(
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Max), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Max), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Max(
+ _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 (Vector64<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((UInt16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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.LoadVector64((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector64_UInt16();
+ var result = AdvSimd.Max(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__Max_Vector64_UInt16();
+
+ fixed (Vector64<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Max(_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 (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Max(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.Max(
+ AdvSimd.LoadVector64((UInt16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt16> op1, Vector64<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] left, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Max(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<UInt16>(Vector64<UInt16>, Vector64<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 Max_Vector64_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__Max_Vector64_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__Max_Vector64_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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<UInt32> _fld1;
+ public Vector64<UInt32> _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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Max_Vector64_UInt32 testClass)
+ {
+ var result = AdvSimd.Max(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Max_Vector64_UInt32 testClass)
+ {
+ fixed (Vector64<UInt32>* pFld1 = &_fld1)
+ fixed (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((UInt32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector64<UInt32> _clsVar1;
+ private static Vector64<UInt32> _clsVar2;
+
+ private Vector64<UInt32> _fld1;
+ private Vector64<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Max_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _clsVar2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ }
+
+ public SimpleBinaryOpTest__Max_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.Max(
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Max(
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Max), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Max), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Max(
+ _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 (Vector64<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((UInt32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Max(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.LoadVector64((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Max(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Max_Vector64_UInt32();
+ var result = AdvSimd.Max(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__Max_Vector64_UInt32();
+
+ fixed (Vector64<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Max(_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 (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Max(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Max(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.Max(
+ AdvSimd.LoadVector64((UInt32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt32> op1, Vector64<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] left, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Max(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Max)}<UInt32>(Vector64<UInt32>, Vector64<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 Min_Vector128_Byte()
+ {
+ var test = new SimpleBinaryOpTest__Min_Vector128_Byte();
+
+ 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__Min_Vector128_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector128<Byte> _fld1;
+ public Vector128<Byte> _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<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Min_Vector128_Byte testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector128_Byte testClass)
+ {
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector128<Byte> _clsVar1;
+ private static Vector128<Byte> _clsVar2;
+
+ private Vector128<Byte> _fld1;
+ private Vector128<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_Vector128_Byte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__Min_Vector128_Byte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.Min(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.Min(
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.Min), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.Min), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.Min(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Byte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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.LoadVector128((Byte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector128_Byte();
+ var result = AdvSimd.Min(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__Min_Vector128_Byte();
+
+ fixed (Vector128<Byte>* pFld1 = &test._fld1)
+ fixed (Vector128<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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.Min(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.Min(
+ AdvSimd.LoadVector128((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector128((Byte*)(&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(Vector128<Byte> op1, Vector128<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, 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];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ 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, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Min(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<Byte>(Vector128<Byte>, Vector128<Byte>): {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 Min_Vector128_Int16()
+ {
+ var test = new SimpleBinaryOpTest__Min_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__Min_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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 Vector128<Int16> _fld1;
+ public Vector128<Int16> _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<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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__Min_Vector128_Int16 testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector128_Int16 testClass)
+ {
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector128<Int16> _clsVar1;
+ private static Vector128<Int16> _clsVar2;
+
+ private Vector128<Int16> _fld1;
+ private Vector128<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_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>>());
+ 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__Min_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 < 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.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Min(
+ Unsafe.Read<Vector128<Int16>>(_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.Min(
+ AdvSimd.LoadVector128((Int16*)(_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.Min), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int16>>(_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.Min), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int16*)(_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.Min(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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.LoadVector128((Int16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector128_Int16();
+ var result = AdvSimd.Min(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__Min_Vector128_Int16();
+
+ fixed (Vector128<Int16>* pFld1 = &test._fld1)
+ fixed (Vector128<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Int16*)(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.Min(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Int16*)(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.Min(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.Min(
+ AdvSimd.LoadVector128((Int16*)(&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(Vector128<Int16> op1, Vector128<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, 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];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Min(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<Int16>(Vector128<Int16>, 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 Min_Vector128_Int32()
+ {
+ var test = new SimpleBinaryOpTest__Min_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__Min_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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 Vector128<Int32> _fld1;
+ public Vector128<Int32> _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<Vector128<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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__Min_Vector128_Int32 testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector128_Int32 testClass)
+ {
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector128<Int32> _clsVar1;
+ private static Vector128<Int32> _clsVar2;
+
+ private Vector128<Int32> _fld1;
+ private Vector128<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_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>>());
+ 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__Min_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 < 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.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Min(
+ Unsafe.Read<Vector128<Int32>>(_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.Min(
+ AdvSimd.LoadVector128((Int32*)(_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.Min), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int32>>(_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.Min), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int32*)(_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.Min(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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.LoadVector128((Int32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector128_Int32();
+ var result = AdvSimd.Min(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__Min_Vector128_Int32();
+
+ fixed (Vector128<Int32>* pFld1 = &test._fld1)
+ fixed (Vector128<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Int32*)(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.Min(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Int32*)(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.Min(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.Min(
+ AdvSimd.LoadVector128((Int32*)(&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(Vector128<Int32> op1, Vector128<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, 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];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Min(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<Int32>(Vector128<Int32>, 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 Min_Vector128_SByte()
+ {
+ var test = new SimpleBinaryOpTest__Min_Vector128_SByte();
+
+ 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__Min_Vector128_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector128<SByte> _fld1;
+ public Vector128<SByte> _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<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Min_Vector128_SByte testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector128_SByte testClass)
+ {
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector128<SByte> _clsVar1;
+ private static Vector128<SByte> _clsVar2;
+
+ private Vector128<SByte> _fld1;
+ private Vector128<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_Vector128_SByte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__Min_Vector128_SByte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Min(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.Min(
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.Min), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.Min), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.Min(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector128_SByte();
+ var result = AdvSimd.Min(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__Min_Vector128_SByte();
+
+ fixed (Vector128<SByte>* pFld1 = &test._fld1)
+ fixed (Vector128<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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.Min(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.Min(
+ AdvSimd.LoadVector128((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector128((SByte*)(&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(Vector128<SByte> op1, Vector128<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, 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];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ 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, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Min(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<SByte>(Vector128<SByte>, Vector128<SByte>): {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 Min_Vector128_Single()
+ {
+ var test = new SimpleBinaryOpTest__Min_Vector128_Single();
+
+ 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__Min_Vector128_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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 Vector128<Single> _fld1;
+ public Vector128<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Min_Vector128_Single testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector128_Single testClass)
+ {
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_Vector128_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Min_Vector128_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.Min(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_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.Min(
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_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.Min), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(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.Min), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Min(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Single*)(pClsVar1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector128_Single();
+ var result = AdvSimd.Min(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__Min_Vector128_Single();
+
+ fixed (Vector128<Single>* pFld1 = &test._fld1)
+ fixed (Vector128<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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.Min(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.Min(
+ AdvSimd.LoadVector128((Single*)(&test._fld1)),
+ AdvSimd.LoadVector128((Single*)(&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(Vector128<Single> op1, Vector128<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Min(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<Single>(Vector128<Single>, Vector128<Single>): {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 Min_Vector128_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__Min_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__Min_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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 Vector128<UInt16> _fld1;
+ public Vector128<UInt16> _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<Vector128<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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__Min_Vector128_UInt16 testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector128_UInt16 testClass)
+ {
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector128<UInt16> _clsVar1;
+ private static Vector128<UInt16> _clsVar2;
+
+ private Vector128<UInt16> _fld1;
+ private Vector128<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_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>>());
+ 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__Min_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 < 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.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.Min(
+ Unsafe.Read<Vector128<UInt16>>(_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.Min(
+ AdvSimd.LoadVector128((UInt16*)(_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.Min), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt16>>(_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.Min), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt16*)(_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.Min(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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.LoadVector128((UInt16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector128_UInt16();
+ var result = AdvSimd.Min(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__Min_Vector128_UInt16();
+
+ fixed (Vector128<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((UInt16*)(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.Min(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((UInt16*)(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.Min(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.Min(
+ AdvSimd.LoadVector128((UInt16*)(&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(Vector128<UInt16> op1, Vector128<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, 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];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Min(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<UInt16>(Vector128<UInt16>, 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 Min_Vector128_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__Min_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__Min_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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 Vector128<UInt32> _fld1;
+ public Vector128<UInt32> _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<Vector128<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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__Min_Vector128_UInt32 testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector128_UInt32 testClass)
+ {
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector128<UInt32> _clsVar1;
+ private static Vector128<UInt32> _clsVar2;
+
+ private Vector128<UInt32> _fld1;
+ private Vector128<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_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>>());
+ 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__Min_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 < 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.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.Min(
+ Unsafe.Read<Vector128<UInt32>>(_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.Min(
+ AdvSimd.LoadVector128((UInt32*)(_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.Min), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt32>>(_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.Min), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt32*)(_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.Min(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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.LoadVector128((UInt32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector128_UInt32();
+ var result = AdvSimd.Min(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__Min_Vector128_UInt32();
+
+ fixed (Vector128<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((UInt32*)(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.Min(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector128((UInt32*)(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.Min(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.Min(
+ AdvSimd.LoadVector128((UInt32*)(&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(Vector128<UInt32> op1, Vector128<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, 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];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Min(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<UInt32>(Vector128<UInt32>, 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 Min_Vector64_Byte()
+ {
+ var test = new SimpleBinaryOpTest__Min_Vector64_Byte();
+
+ 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__Min_Vector64_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector64<Byte> _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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Min_Vector64_Byte testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector64_Byte testClass)
+ {
+ fixed (Vector64<Byte>* pFld1 = &_fld1)
+ fixed (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector64<Byte> _clsVar1;
+ private static Vector64<Byte> _clsVar2;
+
+ private Vector64<Byte> _fld1;
+ private Vector64<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__Min_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.Min(
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_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.Min(
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_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.Min), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Min), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Min(
+ _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 (Vector64<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector64((Byte*)(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<Vector64<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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.LoadVector64((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector64_Byte();
+ var result = AdvSimd.Min(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__Min_Vector64_Byte();
+
+ fixed (Vector64<Byte>* pFld1 = &test._fld1)
+ fixed (Vector64<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Min(_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 (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(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.Min(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.Min(
+ AdvSimd.LoadVector64((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector64((Byte*)(&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, Vector64<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[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<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Min(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<Byte>(Vector64<Byte>, Vector64<Byte>): {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 Min_Vector64_Int16()
+ {
+ var test = new SimpleBinaryOpTest__Min_Vector64_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__Min_Vector64_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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<Int16> _fld1;
+ public Vector64<Int16> _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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Min_Vector64_Int16 testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector64_Int16 testClass)
+ {
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ fixed (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((Int16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector64<Int16> _clsVar1;
+ private static Vector64<Int16> _clsVar2;
+
+ private Vector64<Int16> _fld1;
+ private Vector64<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ }
+
+ public SimpleBinaryOpTest__Min_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Min(
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Min(
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Min), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Min), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Min(
+ _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 (Vector64<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Int16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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.LoadVector64((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector64_Int16();
+ var result = AdvSimd.Min(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__Min_Vector64_Int16();
+
+ fixed (Vector64<Int16>* pFld1 = &test._fld1)
+ fixed (Vector64<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Min(_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 (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Min(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.Min(
+ AdvSimd.LoadVector64((Int16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int16> op1, Vector64<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Min(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<Int16>(Vector64<Int16>, Vector64<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 Min_Vector64_Int32()
+ {
+ var test = new SimpleBinaryOpTest__Min_Vector64_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__Min_Vector64_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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<Int32> _fld1;
+ public Vector64<Int32> _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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref testStruct._fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Min_Vector64_Int32 testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector64_Int32 testClass)
+ {
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ fixed (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((Int32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector64<Int32> _clsVar1;
+ private static Vector64<Int32> _clsVar2;
+
+ private Vector64<Int32> _fld1;
+ private Vector64<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ }
+
+ public SimpleBinaryOpTest__Min_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Min(
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Min(
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Min), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Min), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Min(
+ _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 (Vector64<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Int32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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.LoadVector64((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector64_Int32();
+ var result = AdvSimd.Min(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__Min_Vector64_Int32();
+
+ fixed (Vector64<Int32>* pFld1 = &test._fld1)
+ fixed (Vector64<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Min(_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 (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Min(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.Min(
+ AdvSimd.LoadVector64((Int32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int32> op1, Vector64<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Min(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<Int32>(Vector64<Int32>, Vector64<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 Min_Vector64_SByte()
+ {
+ var test = new SimpleBinaryOpTest__Min_Vector64_SByte();
+
+ 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__Min_Vector64_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector64<SByte> _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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Min_Vector64_SByte testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector64_SByte testClass)
+ {
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ fixed (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector64<SByte> _clsVar1;
+ private static Vector64<SByte> _clsVar2;
+
+ private Vector64<SByte> _fld1;
+ private Vector64<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__Min_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Min(
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_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.Min(
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_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.Min), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Min), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Min(
+ _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 (Vector64<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector64((SByte*)(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<Vector64<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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.LoadVector64((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector64_SByte();
+ var result = AdvSimd.Min(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__Min_Vector64_SByte();
+
+ fixed (Vector64<SByte>* pFld1 = &test._fld1)
+ fixed (Vector64<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Min(_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 (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(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.Min(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.Min(
+ AdvSimd.LoadVector64((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector64((SByte*)(&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, Vector64<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[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<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Min(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<SByte>(Vector64<SByte>, Vector64<SByte>): {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 Min_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__Min_Vector64_Single();
+
+ 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__Min_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Min_Vector64_Single testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Min_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.Min(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.Min(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.Min), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(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.Min), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Min(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector64_Single();
+ var result = AdvSimd.Min(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__Min_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.Min(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.Min(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Min(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<Single>(Vector64<Single>, Vector64<Single>): {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 Min_Vector64_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__Min_Vector64_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__Min_Vector64_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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<UInt16> _fld1;
+ public Vector64<UInt16> _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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Min_Vector64_UInt16 testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector64_UInt16 testClass)
+ {
+ fixed (Vector64<UInt16>* pFld1 = &_fld1)
+ fixed (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((UInt16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector64<UInt16> _clsVar1;
+ private static Vector64<UInt16> _clsVar2;
+
+ private Vector64<UInt16> _fld1;
+ private Vector64<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _clsVar2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ }
+
+ public SimpleBinaryOpTest__Min_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.Min(
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Min(
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Min), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Min), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Min(
+ _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 (Vector64<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((UInt16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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.LoadVector64((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector64_UInt16();
+ var result = AdvSimd.Min(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__Min_Vector64_UInt16();
+
+ fixed (Vector64<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Min(_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 (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Min(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.Min(
+ AdvSimd.LoadVector64((UInt16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt16> op1, Vector64<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] left, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Min(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<UInt16>(Vector64<UInt16>, Vector64<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 Min_Vector64_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__Min_Vector64_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__Min_Vector64_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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<UInt32> _fld1;
+ public Vector64<UInt32> _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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Min_Vector64_UInt32 testClass)
+ {
+ var result = AdvSimd.Min(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Min_Vector64_UInt32 testClass)
+ {
+ fixed (Vector64<UInt32>* pFld1 = &_fld1)
+ fixed (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((UInt32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector64<UInt32> _clsVar1;
+ private static Vector64<UInt32> _clsVar2;
+
+ private Vector64<UInt32> _fld1;
+ private Vector64<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Min_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _clsVar2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ }
+
+ public SimpleBinaryOpTest__Min_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.Min(
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Min(
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Min), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Min), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Min(
+ _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 (Vector64<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((UInt32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Min(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.LoadVector64((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Min(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Min_Vector64_UInt32();
+ var result = AdvSimd.Min(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__Min_Vector64_UInt32();
+
+ fixed (Vector64<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Min(_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 (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Min(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Min(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.Min(
+ AdvSimd.LoadVector64((UInt32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt32> op1, Vector64<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] left, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Min(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Min)}<UInt32>(Vector64<UInt32>, Vector64<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 Multiply_Vector128_Byte()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_Vector128_Byte();
+
+ 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__Multiply_Vector128_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector128<Byte> _fld1;
+ public Vector128<Byte> _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<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Multiply_Vector128_Byte testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector128_Byte testClass)
+ {
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector128<Byte> _clsVar1;
+ private static Vector128<Byte> _clsVar2;
+
+ private Vector128<Byte> _fld1;
+ private Vector128<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_Vector128_Byte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__Multiply_Vector128_Byte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.Multiply(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.Multiply(
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.Multiply), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.Multiply), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.Multiply(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Byte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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.LoadVector128((Byte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector128_Byte();
+ var result = AdvSimd.Multiply(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__Multiply_Vector128_Byte();
+
+ fixed (Vector128<Byte>* pFld1 = &test._fld1)
+ fixed (Vector128<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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.Multiply(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.Multiply(
+ AdvSimd.LoadVector128((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector128((Byte*)(&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(Vector128<Byte> op1, Vector128<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, 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];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ 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, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Multiply(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<Byte>(Vector128<Byte>, Vector128<Byte>): {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 Multiply_Vector128_Int16()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_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__Multiply_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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 Vector128<Int16> _fld1;
+ public Vector128<Int16> _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<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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__Multiply_Vector128_Int16 testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector128_Int16 testClass)
+ {
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector128<Int16> _clsVar1;
+ private static Vector128<Int16> _clsVar2;
+
+ private Vector128<Int16> _fld1;
+ private Vector128<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_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>>());
+ 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__Multiply_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 < 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.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Multiply(
+ Unsafe.Read<Vector128<Int16>>(_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.Multiply(
+ AdvSimd.LoadVector128((Int16*)(_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.Multiply), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int16>>(_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.Multiply), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int16*)(_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.Multiply(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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.LoadVector128((Int16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector128_Int16();
+ var result = AdvSimd.Multiply(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__Multiply_Vector128_Int16();
+
+ fixed (Vector128<Int16>* pFld1 = &test._fld1)
+ fixed (Vector128<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Int16*)(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.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Int16*)(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.Multiply(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.Multiply(
+ AdvSimd.LoadVector128((Int16*)(&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(Vector128<Int16> op1, Vector128<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, 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];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Multiply(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<Int16>(Vector128<Int16>, 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 Multiply_Vector128_Int32()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_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__Multiply_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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 Vector128<Int32> _fld1;
+ public Vector128<Int32> _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<Vector128<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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__Multiply_Vector128_Int32 testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector128_Int32 testClass)
+ {
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector128<Int32> _clsVar1;
+ private static Vector128<Int32> _clsVar2;
+
+ private Vector128<Int32> _fld1;
+ private Vector128<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_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>>());
+ 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__Multiply_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 < 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.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Multiply(
+ Unsafe.Read<Vector128<Int32>>(_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.Multiply(
+ AdvSimd.LoadVector128((Int32*)(_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.Multiply), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int32>>(_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.Multiply), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int32*)(_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.Multiply(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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.LoadVector128((Int32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector128_Int32();
+ var result = AdvSimd.Multiply(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__Multiply_Vector128_Int32();
+
+ fixed (Vector128<Int32>* pFld1 = &test._fld1)
+ fixed (Vector128<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Int32*)(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.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Int32*)(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.Multiply(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.Multiply(
+ AdvSimd.LoadVector128((Int32*)(&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(Vector128<Int32> op1, Vector128<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, 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];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Multiply(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<Int32>(Vector128<Int32>, 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 Multiply_Vector128_SByte()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_Vector128_SByte();
+
+ 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__Multiply_Vector128_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector128<SByte> _fld1;
+ public Vector128<SByte> _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<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Multiply_Vector128_SByte testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector128_SByte testClass)
+ {
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector128<SByte> _clsVar1;
+ private static Vector128<SByte> _clsVar2;
+
+ private Vector128<SByte> _fld1;
+ private Vector128<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_Vector128_SByte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__Multiply_Vector128_SByte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Multiply(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.Multiply(
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.Multiply), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.Multiply), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.Multiply(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector128_SByte();
+ var result = AdvSimd.Multiply(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__Multiply_Vector128_SByte();
+
+ fixed (Vector128<SByte>* pFld1 = &test._fld1)
+ fixed (Vector128<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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.Multiply(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.Multiply(
+ AdvSimd.LoadVector128((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector128((SByte*)(&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(Vector128<SByte> op1, Vector128<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, 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];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ 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, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Multiply(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<SByte>(Vector128<SByte>, Vector128<SByte>): {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 Multiply_Vector128_Single()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_Vector128_Single();
+
+ 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__Multiply_Vector128_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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 Vector128<Single> _fld1;
+ public Vector128<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Multiply_Vector128_Single testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector128_Single testClass)
+ {
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_Vector128_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Multiply_Vector128_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.Multiply(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_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.Multiply(
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_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.Multiply), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(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.Multiply), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Multiply(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Single*)(pClsVar1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector128_Single();
+ var result = AdvSimd.Multiply(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__Multiply_Vector128_Single();
+
+ fixed (Vector128<Single>* pFld1 = &test._fld1)
+ fixed (Vector128<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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.Multiply(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.Multiply(
+ AdvSimd.LoadVector128((Single*)(&test._fld1)),
+ AdvSimd.LoadVector128((Single*)(&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(Vector128<Single> op1, Vector128<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Multiply(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<Single>(Vector128<Single>, Vector128<Single>): {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 Multiply_Vector128_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_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__Multiply_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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 Vector128<UInt16> _fld1;
+ public Vector128<UInt16> _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<Vector128<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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__Multiply_Vector128_UInt16 testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector128_UInt16 testClass)
+ {
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector128<UInt16> _clsVar1;
+ private static Vector128<UInt16> _clsVar2;
+
+ private Vector128<UInt16> _fld1;
+ private Vector128<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_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>>());
+ 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__Multiply_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 < 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.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.Multiply(
+ Unsafe.Read<Vector128<UInt16>>(_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.Multiply(
+ AdvSimd.LoadVector128((UInt16*)(_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.Multiply), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt16>>(_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.Multiply), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt16*)(_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.Multiply(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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.LoadVector128((UInt16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector128_UInt16();
+ var result = AdvSimd.Multiply(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__Multiply_Vector128_UInt16();
+
+ fixed (Vector128<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((UInt16*)(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.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((UInt16*)(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.Multiply(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.Multiply(
+ AdvSimd.LoadVector128((UInt16*)(&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(Vector128<UInt16> op1, Vector128<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, 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];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Multiply(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<UInt16>(Vector128<UInt16>, 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 Multiply_Vector128_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_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__Multiply_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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 Vector128<UInt32> _fld1;
+ public Vector128<UInt32> _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<Vector128<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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__Multiply_Vector128_UInt32 testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector128_UInt32 testClass)
+ {
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector128<UInt32> _clsVar1;
+ private static Vector128<UInt32> _clsVar2;
+
+ private Vector128<UInt32> _fld1;
+ private Vector128<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_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>>());
+ 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__Multiply_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 < 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.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.Multiply(
+ Unsafe.Read<Vector128<UInt32>>(_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.Multiply(
+ AdvSimd.LoadVector128((UInt32*)(_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.Multiply), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt32>>(_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.Multiply), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt32*)(_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.Multiply(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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.LoadVector128((UInt32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector128_UInt32();
+ var result = AdvSimd.Multiply(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__Multiply_Vector128_UInt32();
+
+ fixed (Vector128<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((UInt32*)(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.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector128((UInt32*)(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.Multiply(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.Multiply(
+ AdvSimd.LoadVector128((UInt32*)(&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(Vector128<UInt32> op1, Vector128<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, 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];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Multiply(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<UInt32>(Vector128<UInt32>, 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 Multiply_Vector64_Byte()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_Byte();
+
+ 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__Multiply_Vector64_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector64<Byte> _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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Multiply_Vector64_Byte testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector64_Byte testClass)
+ {
+ fixed (Vector64<Byte>* pFld1 = &_fld1)
+ fixed (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector64<Byte> _clsVar1;
+ private static Vector64<Byte> _clsVar2;
+
+ private Vector64<Byte> _fld1;
+ private Vector64<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__Multiply_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.Multiply(
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_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.Multiply(
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_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.Multiply), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Multiply), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Multiply(
+ _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 (Vector64<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector64((Byte*)(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<Vector64<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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.LoadVector64((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_Byte();
+ var result = AdvSimd.Multiply(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__Multiply_Vector64_Byte();
+
+ fixed (Vector64<Byte>* pFld1 = &test._fld1)
+ fixed (Vector64<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Multiply(_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 (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(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.Multiply(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.Multiply(
+ AdvSimd.LoadVector64((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector64((Byte*)(&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, Vector64<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[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<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Multiply(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<Byte>(Vector64<Byte>, Vector64<Byte>): {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 Multiply_Vector64_Int16()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_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__Multiply_Vector64_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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<Int16> _fld1;
+ public Vector64<Int16> _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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Multiply_Vector64_Int16 testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector64_Int16 testClass)
+ {
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ fixed (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((Int16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector64<Int16> _clsVar1;
+ private static Vector64<Int16> _clsVar2;
+
+ private Vector64<Int16> _fld1;
+ private Vector64<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ }
+
+ public SimpleBinaryOpTest__Multiply_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Multiply(
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Multiply(
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Multiply), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Multiply), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Multiply(
+ _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 (Vector64<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Int16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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.LoadVector64((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_Int16();
+ var result = AdvSimd.Multiply(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__Multiply_Vector64_Int16();
+
+ fixed (Vector64<Int16>* pFld1 = &test._fld1)
+ fixed (Vector64<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Multiply(_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 (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Multiply(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.Multiply(
+ AdvSimd.LoadVector64((Int16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int16> op1, Vector64<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Multiply(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<Int16>(Vector64<Int16>, Vector64<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 Multiply_Vector64_Int32()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_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__Multiply_Vector64_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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<Int32> _fld1;
+ public Vector64<Int32> _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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref testStruct._fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Multiply_Vector64_Int32 testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector64_Int32 testClass)
+ {
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ fixed (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((Int32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector64<Int32> _clsVar1;
+ private static Vector64<Int32> _clsVar2;
+
+ private Vector64<Int32> _fld1;
+ private Vector64<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ }
+
+ public SimpleBinaryOpTest__Multiply_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Multiply(
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Multiply(
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Multiply), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Multiply), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Multiply(
+ _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 (Vector64<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Int32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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.LoadVector64((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_Int32();
+ var result = AdvSimd.Multiply(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__Multiply_Vector64_Int32();
+
+ fixed (Vector64<Int32>* pFld1 = &test._fld1)
+ fixed (Vector64<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Multiply(_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 (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Multiply(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.Multiply(
+ AdvSimd.LoadVector64((Int32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int32> op1, Vector64<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Multiply(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<Int32>(Vector64<Int32>, Vector64<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 Multiply_Vector64_SByte()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_SByte();
+
+ 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__Multiply_Vector64_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector64<SByte> _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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Multiply_Vector64_SByte testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector64_SByte testClass)
+ {
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ fixed (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector64<SByte> _clsVar1;
+ private static Vector64<SByte> _clsVar2;
+
+ private Vector64<SByte> _fld1;
+ private Vector64<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__Multiply_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Multiply(
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_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.Multiply(
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_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.Multiply), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Multiply), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Multiply(
+ _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 (Vector64<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector64((SByte*)(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<Vector64<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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.LoadVector64((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_SByte();
+ var result = AdvSimd.Multiply(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__Multiply_Vector64_SByte();
+
+ fixed (Vector64<SByte>* pFld1 = &test._fld1)
+ fixed (Vector64<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Multiply(_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 (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(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.Multiply(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.Multiply(
+ AdvSimd.LoadVector64((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector64((SByte*)(&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, Vector64<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[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<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Multiply(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<SByte>(Vector64<SByte>, Vector64<SByte>): {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 Multiply_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_Single();
+
+ 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__Multiply_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Multiply_Vector64_Single testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Multiply_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.Multiply(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.Multiply(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.Multiply), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(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.Multiply), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Multiply(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_Single();
+ var result = AdvSimd.Multiply(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__Multiply_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.Multiply(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.Multiply(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Multiply(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<Single>(Vector64<Single>, Vector64<Single>): {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 Multiply_Vector64_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_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__Multiply_Vector64_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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<UInt16> _fld1;
+ public Vector64<UInt16> _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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Multiply_Vector64_UInt16 testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector64_UInt16 testClass)
+ {
+ fixed (Vector64<UInt16>* pFld1 = &_fld1)
+ fixed (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((UInt16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector64<UInt16> _clsVar1;
+ private static Vector64<UInt16> _clsVar2;
+
+ private Vector64<UInt16> _fld1;
+ private Vector64<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _clsVar2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ }
+
+ public SimpleBinaryOpTest__Multiply_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.Multiply(
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Multiply(
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Multiply), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Multiply), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Multiply(
+ _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 (Vector64<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((UInt16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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.LoadVector64((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_UInt16();
+ var result = AdvSimd.Multiply(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__Multiply_Vector64_UInt16();
+
+ fixed (Vector64<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Multiply(_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 (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Multiply(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.Multiply(
+ AdvSimd.LoadVector64((UInt16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt16> op1, Vector64<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] left, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Multiply(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<UInt16>(Vector64<UInt16>, Vector64<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 Multiply_Vector64_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_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__Multiply_Vector64_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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<UInt32> _fld1;
+ public Vector64<UInt32> _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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Multiply_Vector64_UInt32 testClass)
+ {
+ var result = AdvSimd.Multiply(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Multiply_Vector64_UInt32 testClass)
+ {
+ fixed (Vector64<UInt32>* pFld1 = &_fld1)
+ fixed (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((UInt32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector64<UInt32> _clsVar1;
+ private static Vector64<UInt32> _clsVar2;
+
+ private Vector64<UInt32> _fld1;
+ private Vector64<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Multiply_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _clsVar2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ }
+
+ public SimpleBinaryOpTest__Multiply_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.Multiply(
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Multiply(
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Multiply), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Multiply), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Multiply(
+ _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 (Vector64<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((UInt32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Multiply(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.LoadVector64((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Multiply(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Multiply_Vector64_UInt32();
+ var result = AdvSimd.Multiply(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__Multiply_Vector64_UInt32();
+
+ fixed (Vector64<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Multiply(_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 (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Multiply(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Multiply(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.Multiply(
+ AdvSimd.LoadVector64((UInt32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt32> op1, Vector64<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] left, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Multiply(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Multiply)}<UInt32>(Vector64<UInt32>, Vector64<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 MultiplyScalar_Vector64_Double()
+ {
+ var test = new SimpleBinaryOpTest__MultiplyScalar_Vector64_Double();
+
+ 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__MultiplyScalar_Vector64_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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<Double> _fld1;
+ public Vector64<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__MultiplyScalar_Vector64_Double testClass)
+ {
+ var result = AdvSimd.MultiplyScalar(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__MultiplyScalar_Vector64_Double testClass)
+ {
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.MultiplyScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector64<Double> _clsVar1;
+ private static Vector64<Double> _clsVar2;
+
+ private Vector64<Double> _fld1;
+ private Vector64<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__MultiplyScalar_Vector64_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ }
+
+ public SimpleBinaryOpTest__MultiplyScalar_Vector64_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[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.MultiplyScalar(
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_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.MultiplyScalar(
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_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.MultiplyScalar), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(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.MultiplyScalar), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.MultiplyScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.MultiplyScalar(
+ AdvSimd.LoadVector64((Double*)(pClsVar1)),
+ AdvSimd.LoadVector64((Double*)(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<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.MultiplyScalar(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((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.MultiplyScalar(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__MultiplyScalar_Vector64_Double();
+ var result = AdvSimd.MultiplyScalar(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__MultiplyScalar_Vector64_Double();
+
+ fixed (Vector64<Double>* pFld1 = &test._fld1)
+ fixed (Vector64<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.MultiplyScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.MultiplyScalar(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.MultiplyScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(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.MultiplyScalar(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.MultiplyScalar(
+ AdvSimd.LoadVector64((Double*)(&test._fld1)),
+ AdvSimd.LoadVector64((Double*)(&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<Double> op1, Vector64<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(Helpers.Multiply(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.MultiplyScalar)}<Double>(Vector64<Double>, Vector64<Double>): {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 MultiplyScalar_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__MultiplyScalar_Vector64_Single();
+
+ 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__MultiplyScalar_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__MultiplyScalar_Vector64_Single testClass)
+ {
+ var result = AdvSimd.MultiplyScalar(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__MultiplyScalar_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.MultiplyScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__MultiplyScalar_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__MultiplyScalar_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.MultiplyScalar(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.MultiplyScalar(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.MultiplyScalar), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(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.MultiplyScalar), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.MultiplyScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.MultiplyScalar(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.MultiplyScalar(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.MultiplyScalar(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__MultiplyScalar_Vector64_Single();
+ var result = AdvSimd.MultiplyScalar(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__MultiplyScalar_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.MultiplyScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.MultiplyScalar(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.MultiplyScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.MultiplyScalar(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.MultiplyScalar(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(Helpers.Multiply(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.MultiplyScalar)}<Single>(Vector64<Single>, Vector64<Single>): {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 Negate_Vector128_Int16()
+ {
+ var test = new SimpleUnaryOpTest__Negate_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__Negate_Vector128_Int16
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int16[] inArray1, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ 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<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__Negate_Vector128_Int16 testClass)
+ {
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Negate_Vector128_Int16 testClass)
+ {
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ 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<Vector128<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+
+ private static Vector128<Int16> _clsVar1;
+
+ private Vector128<Int16> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Negate_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__Negate_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 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.Negate(
+ 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.Negate(
+ 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.Negate), new Type[] { typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Negate), new Type[] { typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Negate(
+ _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.Negate(
+ 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.Negate(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.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Negate_Vector128_Int16();
+ var result = AdvSimd.Negate(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__Negate_Vector128_Int16();
+
+ fixed (Vector128<Int16>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Negate(
+ 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.Negate(_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.Negate(
+ 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.Negate(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.Negate(
+ 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];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] outArray = new Int16[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<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Negate(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Negate)}<Int16>(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 Negate_Vector128_Int32()
+ {
+ var test = new SimpleUnaryOpTest__Negate_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__Negate_Vector128_Int32
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int32[] inArray1, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ 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<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__Negate_Vector128_Int32 testClass)
+ {
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Negate_Vector128_Int32 testClass)
+ {
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ 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<Vector128<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+
+ private static Vector128<Int32> _clsVar1;
+
+ private Vector128<Int32> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Negate_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__Negate_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 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.Negate(
+ 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.Negate(
+ 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.Negate), new Type[] { typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Negate), new Type[] { typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Negate(
+ _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.Negate(
+ 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.Negate(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.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Negate_Vector128_Int32();
+ var result = AdvSimd.Negate(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__Negate_Vector128_Int32();
+
+ fixed (Vector128<Int32>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Negate(
+ 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.Negate(_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.Negate(
+ 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.Negate(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.Negate(
+ 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];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] outArray = new Int32[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<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Negate(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Negate)}<Int32>(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 Negate_Vector128_SByte()
+ {
+ var test = new SimpleUnaryOpTest__Negate_Vector128_SByte();
+
+ 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__Negate_Vector128_SByte
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(SByte[] inArray1, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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<SByte> _fld1;
+
+ 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<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Negate_Vector128_SByte testClass)
+ {
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Negate_Vector128_SByte testClass)
+ {
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector128((SByte*)(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<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+
+ private static Vector128<SByte> _clsVar1;
+
+ private Vector128<SByte> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Negate_Vector128_SByte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ }
+
+ public SimpleUnaryOpTest__Negate_Vector128_SByte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Negate(
+ Unsafe.Read<Vector128<SByte>>(_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.Negate(
+ AdvSimd.LoadVector128((SByte*)(_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.Negate), new Type[] { typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Negate), new Type[] { typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Negate(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector128((SByte*)(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<SByte>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Negate_Vector128_SByte();
+ var result = AdvSimd.Negate(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__Negate_Vector128_SByte();
+
+ fixed (Vector128<SByte>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector128((SByte*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector128((SByte*)(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.Negate(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.Negate(
+ AdvSimd.LoadVector128((SByte*)(&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<SByte> op1, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Negate(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Negate)}<SByte>(Vector128<SByte>): {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 Negate_Vector128_Single()
+ {
+ var test = new SimpleUnaryOpTest__Negate_Vector128_Single();
+
+ 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__Negate_Vector128_Single
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, 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<Single> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Negate_Vector128_Single testClass)
+ {
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Negate_Vector128_Single testClass)
+ {
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector128((Single*)(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<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+
+ private Vector128<Single> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Negate_Vector128_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ }
+
+ public SimpleUnaryOpTest__Negate_Vector128_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, new Single[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.Negate(
+ Unsafe.Read<Vector128<Single>>(_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.Negate(
+ AdvSimd.LoadVector128((Single*)(_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.Negate), new Type[] { typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Negate), new Type[] { typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Negate(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Single>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector128((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Negate_Vector128_Single();
+ var result = AdvSimd.Negate(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__Negate_Vector128_Single();
+
+ fixed (Vector128<Single>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector128((Single*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector128((Single*)(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.Negate(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.Negate(
+ AdvSimd.LoadVector128((Single*)(&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<Single> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Negate(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Negate)}<Single>(Vector128<Single>): {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 Negate_Vector64_Int16()
+ {
+ var test = new SimpleUnaryOpTest__Negate_Vector64_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__Negate_Vector64_Int16
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int16[] inArray1, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ 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<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 Vector64<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<Vector64<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Negate_Vector64_Int16 testClass)
+ {
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Negate_Vector64_Int16 testClass)
+ {
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((Int16*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+
+ private static Vector64<Int16> _clsVar1;
+
+ private Vector64<Int16> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Negate_Vector64_Int16()
+ {
+ 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>>());
+ }
+
+ public SimpleUnaryOpTest__Negate_Vector64_Int16()
+ {
+ 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 < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Negate(
+ Unsafe.Read<Vector64<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.Negate(
+ AdvSimd.LoadVector64((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.Negate), new Type[] { typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int16>>(_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.Negate), new Type[] { typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int16*)(_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.Negate(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int16>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((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<Vector64<Int16>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Negate_Vector64_Int16();
+ var result = AdvSimd.Negate(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__Negate_Vector64_Int16();
+
+ fixed (Vector64<Int16>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((Int16*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((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.Negate(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.Negate(
+ AdvSimd.LoadVector64((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(Vector64<Int16> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, 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 = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ 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<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Negate(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Negate)}<Int16>(Vector64<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 Negate_Vector64_Int32()
+ {
+ var test = new SimpleUnaryOpTest__Negate_Vector64_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__Negate_Vector64_Int32
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int32[] inArray1, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ 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<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 Vector64<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<Vector64<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Negate_Vector64_Int32 testClass)
+ {
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Negate_Vector64_Int32 testClass)
+ {
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((Int32*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+
+ private static Vector64<Int32> _clsVar1;
+
+ private Vector64<Int32> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Negate_Vector64_Int32()
+ {
+ 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>>());
+ }
+
+ public SimpleUnaryOpTest__Negate_Vector64_Int32()
+ {
+ 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 < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Negate(
+ Unsafe.Read<Vector64<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.Negate(
+ AdvSimd.LoadVector64((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.Negate), new Type[] { typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int32>>(_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.Negate), new Type[] { typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int32*)(_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.Negate(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int32>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((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<Vector64<Int32>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Negate_Vector64_Int32();
+ var result = AdvSimd.Negate(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__Negate_Vector64_Int32();
+
+ fixed (Vector64<Int32>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((Int32*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((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.Negate(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.Negate(
+ AdvSimd.LoadVector64((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(Vector64<Int32> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, 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 = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ 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<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Negate(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Negate)}<Int32>(Vector64<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 Negate_Vector64_SByte()
+ {
+ var test = new SimpleUnaryOpTest__Negate_Vector64_SByte();
+
+ 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__Negate_Vector64_SByte
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(SByte[] inArray1, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector64<SByte> _fld1;
+
+ 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>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Negate_Vector64_SByte testClass)
+ {
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Negate_Vector64_SByte testClass)
+ {
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((SByte*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+
+ private static Vector64<SByte> _clsVar1;
+
+ private Vector64<SByte> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Negate_Vector64_SByte()
+ {
+ 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>>());
+ }
+
+ public SimpleUnaryOpTest__Negate_Vector64_SByte()
+ {
+ 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 < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Negate(
+ Unsafe.Read<Vector64<SByte>>(_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.Negate(
+ AdvSimd.LoadVector64((SByte*)(_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.Negate), new Type[] { typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<SByte>>(_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.Negate), new Type[] { typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((SByte*)(_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.Negate(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<SByte>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((SByte*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Negate_Vector64_SByte();
+ var result = AdvSimd.Negate(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__Negate_Vector64_SByte();
+
+ fixed (Vector64<SByte>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((SByte*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((SByte*)(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.Negate(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.Negate(
+ AdvSimd.LoadVector64((SByte*)(&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(Vector64<SByte> op1, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, 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 = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ 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<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Negate(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Negate)}<SByte>(Vector64<SByte>): {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 Negate_Vector64_Single()
+ {
+ var test = new SimpleUnaryOpTest__Negate_Vector64_Single();
+
+ 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__Negate_Vector64_Single
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, 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 Vector64<Single> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Negate_Vector64_Single testClass)
+ {
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Negate_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((Single*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+
+ private Vector64<Single> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Negate_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleUnaryOpTest__Negate_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, new Single[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.Negate(
+ Unsafe.Read<Vector64<Single>>(_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.Negate(
+ AdvSimd.LoadVector64((Single*)(_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.Negate), new Type[] { typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Negate), new Type[] { typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Negate(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((Single*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Negate(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Negate_Vector64_Single();
+ var result = AdvSimd.Negate(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__Negate_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((Single*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Negate(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Negate(
+ AdvSimd.LoadVector64((Single*)(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.Negate(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.Negate(
+ AdvSimd.LoadVector64((Single*)(&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(Vector64<Single> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Negate(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Negate)}<Single>(Vector64<Single>): {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 NegateScalar_Vector64_Double()
+ {
+ var test = new SimpleUnaryOpTest__NegateScalar_Vector64_Double();
+
+ 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__NegateScalar_Vector64_Double
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, 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 Vector64<Double> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__NegateScalar_Vector64_Double testClass)
+ {
+ var result = AdvSimd.NegateScalar(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__NegateScalar_Vector64_Double testClass)
+ {
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.NegateScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+
+ private static Vector64<Double> _clsVar1;
+
+ private Vector64<Double> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__NegateScalar_Vector64_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ }
+
+ public SimpleUnaryOpTest__NegateScalar_Vector64_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, new Double[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.NegateScalar(
+ Unsafe.Read<Vector64<Double>>(_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.NegateScalar(
+ AdvSimd.LoadVector64((Double*)(_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.NegateScalar), new Type[] { typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.NegateScalar), new Type[] { typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.NegateScalar(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Double>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.NegateScalar(
+ AdvSimd.LoadVector64((Double*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.NegateScalar(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.NegateScalar(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__NegateScalar_Vector64_Double();
+ var result = AdvSimd.NegateScalar(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__NegateScalar_Vector64_Double();
+
+ fixed (Vector64<Double>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.NegateScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.NegateScalar(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.NegateScalar(
+ AdvSimd.LoadVector64((Double*)(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.NegateScalar(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.NegateScalar(
+ AdvSimd.LoadVector64((Double*)(&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(Vector64<Double> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(Helpers.Negate(firstOp[0])) != BitConverter.DoubleToInt64Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.NegateScalar)}<Double>(Vector64<Double>): {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 NegateScalar_Vector64_Single()
+ {
+ var test = new SimpleUnaryOpTest__NegateScalar_Vector64_Single();
+
+ 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__NegateScalar_Vector64_Single
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, 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 Vector64<Single> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__NegateScalar_Vector64_Single testClass)
+ {
+ var result = AdvSimd.NegateScalar(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__NegateScalar_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.NegateScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+
+ private Vector64<Single> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__NegateScalar_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleUnaryOpTest__NegateScalar_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, new Single[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.NegateScalar(
+ Unsafe.Read<Vector64<Single>>(_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.NegateScalar(
+ AdvSimd.LoadVector64((Single*)(_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.NegateScalar), new Type[] { typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.NegateScalar), new Type[] { typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.NegateScalar(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.NegateScalar(
+ AdvSimd.LoadVector64((Single*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.NegateScalar(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.NegateScalar(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__NegateScalar_Vector64_Single();
+ var result = AdvSimd.NegateScalar(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__NegateScalar_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.NegateScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.NegateScalar(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.NegateScalar(
+ AdvSimd.LoadVector64((Single*)(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.NegateScalar(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.NegateScalar(
+ AdvSimd.LoadVector64((Single*)(&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(Vector64<Single> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(Helpers.Negate(firstOp[0])) != BitConverter.SingleToInt32Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.NegateScalar)}<Single>(Vector64<Single>): {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 Not_Vector128_Byte()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector128_Byte();
+
+ 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__Not_Vector128_Byte
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Byte[] inArray1, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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<Byte> _fld1;
+
+ 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<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector128_Byte testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector128_Byte testClass)
+ {
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((Byte*)(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<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+
+ private static Vector128<Byte> _clsVar1;
+
+ private Vector128<Byte> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector128_Byte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector128_Byte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ _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.Not(
+ Unsafe.Read<Vector128<Byte>>(_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.Not(
+ AdvSimd.LoadVector128((Byte*)(_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.Not), new Type[] { typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Byte>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((Byte*)(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<Byte>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector128_Byte();
+ var result = AdvSimd.Not(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__Not_Vector128_Byte();
+
+ fixed (Vector128<Byte>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((Byte*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((Byte*)(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.Not(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.Not(
+ AdvSimd.LoadVector128((Byte*)(&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<Byte> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<Byte>(Vector128<Byte>): {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 Not_Vector128_Double()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector128_Double();
+
+ 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__Not_Vector128_Double
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, 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<Double> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector128_Double testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector128_Double testClass)
+ {
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((Double*)(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<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+
+ private Vector128<Double> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector128_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector128_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, new Double[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.Not(
+ Unsafe.Read<Vector128<Double>>(_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.Not(
+ AdvSimd.LoadVector128((Double*)(_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.Not), new Type[] { typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Double>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((Double*)(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<Double>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector128_Double();
+ var result = AdvSimd.Not(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__Not_Vector128_Double();
+
+ fixed (Vector128<Double>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((Double*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((Double*)(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.Not(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.Not(
+ AdvSimd.LoadVector128((Double*)(&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<Double> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.Not(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<Double>(Vector128<Double>): {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 Not_Vector128_Int16()
+ {
+ var test = new SimpleUnaryOpTest__Not_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__Not_Vector128_Int16
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int16[] inArray1, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ 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<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__Not_Vector128_Int16 testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector128_Int16 testClass)
+ {
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ 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<Vector128<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+
+ private static Vector128<Int16> _clsVar1;
+
+ private Vector128<Int16> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_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__Not_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 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.Not(
+ 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.Not(
+ 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.Not), new Type[] { typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _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.Not(
+ 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.Not(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.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector128_Int16();
+ var result = AdvSimd.Not(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__Not_Vector128_Int16();
+
+ fixed (Vector128<Int16>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ 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.Not(_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.Not(
+ 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.Not(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.Not(
+ 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];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] outArray = new Int16[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<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<Int16>(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 Not_Vector128_Int32()
+ {
+ var test = new SimpleUnaryOpTest__Not_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__Not_Vector128_Int32
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int32[] inArray1, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ 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<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__Not_Vector128_Int32 testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector128_Int32 testClass)
+ {
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ 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<Vector128<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+
+ private static Vector128<Int32> _clsVar1;
+
+ private Vector128<Int32> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_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__Not_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 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.Not(
+ 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.Not(
+ 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.Not), new Type[] { typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _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.Not(
+ 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.Not(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.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector128_Int32();
+ var result = AdvSimd.Not(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__Not_Vector128_Int32();
+
+ fixed (Vector128<Int32>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ 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.Not(_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.Not(
+ 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.Not(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.Not(
+ 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];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] outArray = new Int32[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<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<Int32>(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 Not_Vector128_Int64()
+ {
+ var test = new SimpleUnaryOpTest__Not_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__Not_Vector128_Int64
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int64[] inArray1, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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__Not_Vector128_Int64 testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector128_Int64 testClass)
+ {
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ 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<Vector128<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+
+ private static Vector128<Int64> _clsVar1;
+
+ private Vector128<Int64> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_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__Not_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 Int64[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.Not(
+ 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.Not(
+ 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.Not), new Type[] { typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _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.Not(
+ 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.Not(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.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector128_Int64();
+ var result = AdvSimd.Not(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__Not_Vector128_Int64();
+
+ fixed (Vector128<Int64>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ 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.Not(_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.Not(
+ 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.Not(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.Not(
+ 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];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[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<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<Int64>(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 Not_Vector128_SByte()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector128_SByte();
+
+ 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__Not_Vector128_SByte
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(SByte[] inArray1, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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<SByte> _fld1;
+
+ 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<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector128_SByte testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector128_SByte testClass)
+ {
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((SByte*)(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<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+
+ private static Vector128<SByte> _clsVar1;
+
+ private Vector128<SByte> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector128_SByte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector128_SByte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Not(
+ Unsafe.Read<Vector128<SByte>>(_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.Not(
+ AdvSimd.LoadVector128((SByte*)(_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.Not), new Type[] { typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((SByte*)(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<SByte>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector128_SByte();
+ var result = AdvSimd.Not(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__Not_Vector128_SByte();
+
+ fixed (Vector128<SByte>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((SByte*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((SByte*)(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.Not(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.Not(
+ AdvSimd.LoadVector128((SByte*)(&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<SByte> op1, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<SByte>(Vector128<SByte>): {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 Not_Vector128_Single()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector128_Single();
+
+ 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__Not_Vector128_Single
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, 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<Single> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector128_Single testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector128_Single testClass)
+ {
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((Single*)(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<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+
+ private Vector128<Single> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector128_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector128_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, new Single[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.Not(
+ Unsafe.Read<Vector128<Single>>(_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.Not(
+ AdvSimd.LoadVector128((Single*)(_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.Not), new Type[] { typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Single>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector128_Single();
+ var result = AdvSimd.Not(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__Not_Vector128_Single();
+
+ fixed (Vector128<Single>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((Single*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector128((Single*)(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.Not(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.Not(
+ AdvSimd.LoadVector128((Single*)(&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<Single> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Not(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<Single>(Vector128<Single>): {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 Not_Vector128_UInt16()
+ {
+ var test = new SimpleUnaryOpTest__Not_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__Not_Vector128_UInt16
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(UInt16[] inArray1, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ 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<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__Not_Vector128_UInt16 testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector128_UInt16 testClass)
+ {
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ 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<Vector128<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+
+ private static Vector128<UInt16> _clsVar1;
+
+ private Vector128<UInt16> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_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__Not_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 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.Not(
+ 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.Not(
+ 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.Not), new Type[] { typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _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.Not(
+ 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.Not(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.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector128_UInt16();
+ var result = AdvSimd.Not(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__Not_Vector128_UInt16();
+
+ fixed (Vector128<UInt16>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ 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.Not(_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.Not(
+ 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.Not(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.Not(
+ 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];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] outArray = new UInt16[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<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<UInt16>(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 Not_Vector128_UInt32()
+ {
+ var test = new SimpleUnaryOpTest__Not_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__Not_Vector128_UInt32
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(UInt32[] inArray1, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ 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<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__Not_Vector128_UInt32 testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector128_UInt32 testClass)
+ {
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ 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<Vector128<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+
+ private static Vector128<UInt32> _clsVar1;
+
+ private Vector128<UInt32> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_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__Not_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 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.Not(
+ 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.Not(
+ 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.Not), new Type[] { typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _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.Not(
+ 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.Not(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.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector128_UInt32();
+ var result = AdvSimd.Not(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__Not_Vector128_UInt32();
+
+ fixed (Vector128<UInt32>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ 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.Not(_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.Not(
+ 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.Not(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.Not(
+ 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];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] outArray = new UInt32[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<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<UInt32>(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 Not_Vector128_UInt64()
+ {
+ var test = new SimpleUnaryOpTest__Not_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__Not_Vector128_UInt64
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(UInt64[] inArray1, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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__Not_Vector128_UInt64 testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector128_UInt64 testClass)
+ {
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ 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<Vector128<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+
+ private static Vector128<UInt64> _clsVar1;
+
+ private Vector128<UInt64> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_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__Not_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 UInt64[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.Not(
+ 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.Not(
+ 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.Not), new Type[] { typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _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.Not(
+ 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.Not(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.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector128_UInt64();
+ var result = AdvSimd.Not(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__Not_Vector128_UInt64();
+
+ fixed (Vector128<UInt64>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ 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.Not(_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.Not(
+ 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.Not(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.Not(
+ 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];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] outArray = new UInt64[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<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<UInt64>(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;
+ }
+ }
+ }
+}
--- /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 Not_Vector64_Byte()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector64_Byte();
+
+ 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__Not_Vector64_Byte
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Byte[] inArray1, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector64<Byte> _fld1;
+
+ 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>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector64_Byte testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector64_Byte testClass)
+ {
+ fixed (Vector64<Byte>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Byte*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+
+ private static Vector64<Byte> _clsVar1;
+
+ private Vector64<Byte> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector64_Byte()
+ {
+ 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>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector64_Byte()
+ {
+ 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 < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ _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.Not(
+ Unsafe.Read<Vector64<Byte>>(_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.Not(
+ AdvSimd.LoadVector64((Byte*)(_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.Not), new Type[] { typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Byte>>(_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.Not), new Type[] { typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Byte*)(_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.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Byte>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Byte*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector64_Byte();
+ var result = AdvSimd.Not(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__Not_Vector64_Byte();
+
+ fixed (Vector64<Byte>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Byte*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Byte>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Byte*)(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.Not(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.Not(
+ AdvSimd.LoadVector64((Byte*)(&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(Vector64<Byte> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, 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 = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ 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<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<Byte>(Vector64<Byte>): {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 Not_Vector64_Double()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector64_Double();
+
+ 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__Not_Vector64_Double
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, 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 Vector64<Double> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector64_Double testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector64_Double testClass)
+ {
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Double*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+
+ private static Vector64<Double> _clsVar1;
+
+ private Vector64<Double> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector64_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector64_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, new Double[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.Not(
+ Unsafe.Read<Vector64<Double>>(_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.Not(
+ AdvSimd.LoadVector64((Double*)(_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.Not), new Type[] { typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Double>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Double*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector64_Double();
+ var result = AdvSimd.Not(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__Not_Vector64_Double();
+
+ fixed (Vector64<Double>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Double*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Double*)(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.Not(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.Not(
+ AdvSimd.LoadVector64((Double*)(&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(Vector64<Double> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.Not(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<Double>(Vector64<Double>): {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 Not_Vector64_Int16()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector64_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__Not_Vector64_Int16
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int16[] inArray1, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ 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<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 Vector64<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<Vector64<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector64_Int16 testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector64_Int16 testClass)
+ {
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Int16*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+
+ private static Vector64<Int16> _clsVar1;
+
+ private Vector64<Int16> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector64_Int16()
+ {
+ 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>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector64_Int16()
+ {
+ 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 < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Not(
+ Unsafe.Read<Vector64<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.Not(
+ AdvSimd.LoadVector64((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.Not), new Type[] { typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int16>>(_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.Not), new Type[] { typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int16*)(_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.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int16>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((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<Vector64<Int16>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector64_Int16();
+ var result = AdvSimd.Not(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__Not_Vector64_Int16();
+
+ fixed (Vector64<Int16>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Int16*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((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.Not(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.Not(
+ AdvSimd.LoadVector64((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(Vector64<Int16> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, 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 = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ 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<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<Int16>(Vector64<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 Not_Vector64_Int32()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector64_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__Not_Vector64_Int32
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int32[] inArray1, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ 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<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 Vector64<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<Vector64<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector64_Int32 testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector64_Int32 testClass)
+ {
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Int32*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+
+ private static Vector64<Int32> _clsVar1;
+
+ private Vector64<Int32> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector64_Int32()
+ {
+ 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>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector64_Int32()
+ {
+ 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 < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Not(
+ Unsafe.Read<Vector64<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.Not(
+ AdvSimd.LoadVector64((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.Not), new Type[] { typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int32>>(_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.Not), new Type[] { typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int32*)(_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.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int32>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((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<Vector64<Int32>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector64_Int32();
+ var result = AdvSimd.Not(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__Not_Vector64_Int32();
+
+ fixed (Vector64<Int32>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Int32*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((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.Not(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.Not(
+ AdvSimd.LoadVector64((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(Vector64<Int32> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, 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 = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ 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<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<Int32>(Vector64<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 Not_Vector64_Int64()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector64_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__Not_Vector64_Int64
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Int64[] inArray1, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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 Vector64<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<Vector64<Int64>, byte>(ref testStruct._fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector64_Int64 testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector64_Int64 testClass)
+ {
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Int64*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+
+ private static Vector64<Int64> _clsVar1;
+
+ private Vector64<Int64> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector64_Int64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector64_Int64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, new Int64[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.Not(
+ Unsafe.Read<Vector64<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.Not(
+ AdvSimd.LoadVector64((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.Not), new Type[] { typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int64>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((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<Vector64<Int64>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector64_Int64();
+ var result = AdvSimd.Not(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__Not_Vector64_Int64();
+
+ fixed (Vector64<Int64>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Int64*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((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.Not(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.Not(
+ AdvSimd.LoadVector64((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(Vector64<Int64> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<Int64>(Vector64<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 Not_Vector64_SByte()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector64_SByte();
+
+ 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__Not_Vector64_SByte
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(SByte[] inArray1, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector64<SByte> _fld1;
+
+ 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>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector64_SByte testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector64_SByte testClass)
+ {
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((SByte*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+
+ private static Vector64<SByte> _clsVar1;
+
+ private Vector64<SByte> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector64_SByte()
+ {
+ 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>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector64_SByte()
+ {
+ 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 < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Not(
+ Unsafe.Read<Vector64<SByte>>(_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.Not(
+ AdvSimd.LoadVector64((SByte*)(_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.Not), new Type[] { typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<SByte>>(_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.Not), new Type[] { typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((SByte*)(_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.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<SByte>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((SByte*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector64_SByte();
+ var result = AdvSimd.Not(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__Not_Vector64_SByte();
+
+ fixed (Vector64<SByte>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((SByte*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((SByte*)(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.Not(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.Not(
+ AdvSimd.LoadVector64((SByte*)(&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(Vector64<SByte> op1, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, 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 = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ 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<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<SByte>(Vector64<SByte>): {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 Not_Vector64_Single()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector64_Single();
+
+ 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__Not_Vector64_Single
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, 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 Vector64<Single> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector64_Single testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Single*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+
+ private Vector64<Single> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, new Single[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.Not(
+ Unsafe.Read<Vector64<Single>>(_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.Not(
+ AdvSimd.LoadVector64((Single*)(_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.Not), new Type[] { typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Single*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector64_Single();
+ var result = AdvSimd.Not(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__Not_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Single*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((Single*)(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.Not(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.Not(
+ AdvSimd.LoadVector64((Single*)(&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(Vector64<Single> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Not(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<Single>(Vector64<Single>): {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 Not_Vector64_UInt16()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector64_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__Not_Vector64_UInt16
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(UInt16[] inArray1, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ 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<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 Vector64<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<Vector64<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector64_UInt16 testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector64_UInt16 testClass)
+ {
+ fixed (Vector64<UInt16>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((UInt16*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+
+ private static Vector64<UInt16> _clsVar1;
+
+ private Vector64<UInt16> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector64_UInt16()
+ {
+ 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>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector64_UInt16()
+ {
+ 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 < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.Not(
+ Unsafe.Read<Vector64<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.Not(
+ AdvSimd.LoadVector64((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.Not), new Type[] { typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt16>>(_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.Not), new Type[] { typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt16*)(_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.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<UInt16>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((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<Vector64<UInt16>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector64_UInt16();
+ var result = AdvSimd.Not(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__Not_Vector64_UInt16();
+
+ fixed (Vector64<UInt16>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((UInt16*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<UInt16>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((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.Not(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.Not(
+ AdvSimd.LoadVector64((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(Vector64<UInt16> op1, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, 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 = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ 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<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<UInt16>(Vector64<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 Not_Vector64_UInt32()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector64_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__Not_Vector64_UInt32
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(UInt32[] inArray1, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ 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<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 Vector64<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<Vector64<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector64_UInt32 testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector64_UInt32 testClass)
+ {
+ fixed (Vector64<UInt32>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((UInt32*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+
+ private static Vector64<UInt32> _clsVar1;
+
+ private Vector64<UInt32> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector64_UInt32()
+ {
+ 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>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector64_UInt32()
+ {
+ 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 < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.Not(
+ Unsafe.Read<Vector64<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.Not(
+ AdvSimd.LoadVector64((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.Not), new Type[] { typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt32>>(_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.Not), new Type[] { typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt32*)(_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.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<UInt32>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((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<Vector64<UInt32>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector64_UInt32();
+ var result = AdvSimd.Not(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__Not_Vector64_UInt32();
+
+ fixed (Vector64<UInt32>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((UInt32*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<UInt32>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((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.Not(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.Not(
+ AdvSimd.LoadVector64((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(Vector64<UInt32> op1, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, 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 = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ 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<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<UInt32>(Vector64<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 Not_Vector64_UInt64()
+ {
+ var test = new SimpleUnaryOpTest__Not_Vector64_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__Not_Vector64_UInt64
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(UInt64[] inArray1, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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 Vector64<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<Vector64<UInt64>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__Not_Vector64_UInt64 testClass)
+ {
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__Not_Vector64_UInt64 testClass)
+ {
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((UInt64*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+
+ private static Vector64<UInt64> _clsVar1;
+
+ private Vector64<UInt64> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__Not_Vector64_UInt64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _clsVar1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ }
+
+ public SimpleUnaryOpTest__Not_Vector64_UInt64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, new UInt64[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.Not(
+ Unsafe.Read<Vector64<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.Not(
+ AdvSimd.LoadVector64((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.Not), new Type[] { typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.Not), new Type[] { typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Not(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<UInt64>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((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<Vector64<UInt64>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.Not(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__Not_Vector64_UInt64();
+ var result = AdvSimd.Not(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__Not_Vector64_UInt64();
+
+ fixed (Vector64<UInt64>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((UInt64*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Not(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.Not(
+ AdvSimd.LoadVector64((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.Not(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.Not(
+ AdvSimd.LoadVector64((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(Vector64<UInt64> op1, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Not(firstOp[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Not)}<UInt64>(Vector64<UInt64>): {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 Or_Vector128_Byte()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector128_Byte();
+
+ 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__Or_Vector128_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector128<Byte> _fld1;
+ public Vector128<Byte> _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<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector128_Byte testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector128_Byte testClass)
+ {
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector128<Byte> _clsVar1;
+ private static Vector128<Byte> _clsVar2;
+
+ private Vector128<Byte> _fld1;
+ private Vector128<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector128_Byte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector128_Byte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.Or(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.Or(
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.Or), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.Or), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Byte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector128((Byte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector128_Byte();
+ var result = AdvSimd.Or(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__Or_Vector128_Byte();
+
+ fixed (Vector128<Byte>* pFld1 = &test._fld1)
+ fixed (Vector128<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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.Or(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.Or(
+ AdvSimd.LoadVector128((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector128((Byte*)(&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(Vector128<Byte> op1, Vector128<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, 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];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ 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, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<Byte>(Vector128<Byte>, Vector128<Byte>): {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 Or_Vector128_Double()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector128_Double();
+
+ 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__Or_Vector128_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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 Vector128<Double> _fld1;
+ public Vector128<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector128_Double testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector128_Double testClass)
+ {
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+ private static Vector128<Double> _clsVar2;
+
+ private Vector128<Double> _fld1;
+ private Vector128<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector128_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector128_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[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.Or(
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_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.Or(
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_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.Or), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(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.Or), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Double*)(pClsVar1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector128_Double();
+ var result = AdvSimd.Or(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__Or_Vector128_Double();
+
+ fixed (Vector128<Double>* pFld1 = &test._fld1)
+ fixed (Vector128<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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.Or(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.Or(
+ AdvSimd.LoadVector128((Double*)(&test._fld1)),
+ AdvSimd.LoadVector128((Double*)(&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(Vector128<Double> op1, Vector128<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.Or(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<Double>(Vector128<Double>, Vector128<Double>): {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 Or_Vector128_Int16()
+ {
+ var test = new SimpleBinaryOpTest__Or_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__Or_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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 Vector128<Int16> _fld1;
+ public Vector128<Int16> _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<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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__Or_Vector128_Int16 testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector128_Int16 testClass)
+ {
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector128<Int16> _clsVar1;
+ private static Vector128<Int16> _clsVar2;
+
+ private Vector128<Int16> _fld1;
+ private Vector128<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_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>>());
+ 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__Or_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 < 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.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Or(
+ Unsafe.Read<Vector128<Int16>>(_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.Or(
+ AdvSimd.LoadVector128((Int16*)(_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.Or), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int16>>(_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.Or), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int16*)(_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.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector128((Int16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector128_Int16();
+ var result = AdvSimd.Or(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__Or_Vector128_Int16();
+
+ fixed (Vector128<Int16>* pFld1 = &test._fld1)
+ fixed (Vector128<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Int16*)(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.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Int16*)(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.Or(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.Or(
+ AdvSimd.LoadVector128((Int16*)(&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(Vector128<Int16> op1, Vector128<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, 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];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<Int16>(Vector128<Int16>, 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 Or_Vector128_Int32()
+ {
+ var test = new SimpleBinaryOpTest__Or_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__Or_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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 Vector128<Int32> _fld1;
+ public Vector128<Int32> _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<Vector128<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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__Or_Vector128_Int32 testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector128_Int32 testClass)
+ {
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector128<Int32> _clsVar1;
+ private static Vector128<Int32> _clsVar2;
+
+ private Vector128<Int32> _fld1;
+ private Vector128<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_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>>());
+ 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__Or_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 < 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.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Or(
+ Unsafe.Read<Vector128<Int32>>(_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.Or(
+ AdvSimd.LoadVector128((Int32*)(_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.Or), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int32>>(_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.Or), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int32*)(_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.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector128((Int32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector128_Int32();
+ var result = AdvSimd.Or(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__Or_Vector128_Int32();
+
+ fixed (Vector128<Int32>* pFld1 = &test._fld1)
+ fixed (Vector128<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Int32*)(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.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Int32*)(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.Or(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.Or(
+ AdvSimd.LoadVector128((Int32*)(&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(Vector128<Int32> op1, Vector128<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, 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];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<Int32>(Vector128<Int32>, 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 Or_Vector128_Int64()
+ {
+ var test = new SimpleBinaryOpTest__Or_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__Or_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(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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<Int64, 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 Vector128<Int64> _fld1;
+ public Vector128<Int64> _fld2;
+
+ 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>>());
+ 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__Or_Vector128_Int64 testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector128_Int64 testClass)
+ {
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Int64*)(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<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+ private static Int64[] _data2 = new Int64[Op2ElementCount];
+
+ private static Vector128<Int64> _clsVar1;
+ private static Vector128<Int64> _clsVar2;
+
+ private Vector128<Int64> _fld1;
+ private Vector128<Int64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_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>>());
+ 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__Or_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 < 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.GetInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new Int64[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.Or(
+ Unsafe.Read<Vector128<Int64>>(_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.Or(
+ AdvSimd.LoadVector128((Int64*)(_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.Or), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(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.Or), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int64>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Int64*)(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<Vector128<Int64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector128((Int64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector128_Int64();
+ var result = AdvSimd.Or(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__Or_Vector128_Int64();
+
+ fixed (Vector128<Int64>* pFld1 = &test._fld1)
+ fixed (Vector128<Int64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Int64*)(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.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Int64*)(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.Or(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.Or(
+ AdvSimd.LoadVector128((Int64*)(&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(Vector128<Int64> op1, Vector128<Int64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[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<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<Int64>(Vector128<Int64>, 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 Or_Vector128_SByte()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector128_SByte();
+
+ 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__Or_Vector128_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector128<SByte> _fld1;
+ public Vector128<SByte> _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<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector128_SByte testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector128_SByte testClass)
+ {
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector128<SByte> _clsVar1;
+ private static Vector128<SByte> _clsVar2;
+
+ private Vector128<SByte> _fld1;
+ private Vector128<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector128_SByte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector128_SByte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Or(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.Or(
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.Or), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.Or), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector128_SByte();
+ var result = AdvSimd.Or(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__Or_Vector128_SByte();
+
+ fixed (Vector128<SByte>* pFld1 = &test._fld1)
+ fixed (Vector128<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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.Or(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.Or(
+ AdvSimd.LoadVector128((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector128((SByte*)(&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(Vector128<SByte> op1, Vector128<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, 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];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ 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, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<SByte>(Vector128<SByte>, Vector128<SByte>): {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 Or_Vector128_Single()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector128_Single();
+
+ 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__Or_Vector128_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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 Vector128<Single> _fld1;
+ public Vector128<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector128_Single testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector128_Single testClass)
+ {
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector128_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector128_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.Or(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_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.Or(
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_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.Or), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(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.Or), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Single*)(pClsVar1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector128_Single();
+ var result = AdvSimd.Or(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__Or_Vector128_Single();
+
+ fixed (Vector128<Single>* pFld1 = &test._fld1)
+ fixed (Vector128<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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.Or(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.Or(
+ AdvSimd.LoadVector128((Single*)(&test._fld1)),
+ AdvSimd.LoadVector128((Single*)(&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(Vector128<Single> op1, Vector128<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Or(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<Single>(Vector128<Single>, Vector128<Single>): {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 Or_Vector128_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__Or_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__Or_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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 Vector128<UInt16> _fld1;
+ public Vector128<UInt16> _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<Vector128<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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__Or_Vector128_UInt16 testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector128_UInt16 testClass)
+ {
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector128<UInt16> _clsVar1;
+ private static Vector128<UInt16> _clsVar2;
+
+ private Vector128<UInt16> _fld1;
+ private Vector128<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_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>>());
+ 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__Or_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 < 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.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.Or(
+ Unsafe.Read<Vector128<UInt16>>(_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.Or(
+ AdvSimd.LoadVector128((UInt16*)(_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.Or), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt16>>(_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.Or), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt16*)(_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.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector128((UInt16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector128_UInt16();
+ var result = AdvSimd.Or(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__Or_Vector128_UInt16();
+
+ fixed (Vector128<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((UInt16*)(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.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((UInt16*)(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.Or(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.Or(
+ AdvSimd.LoadVector128((UInt16*)(&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(Vector128<UInt16> op1, Vector128<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, 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];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<UInt16>(Vector128<UInt16>, 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 Or_Vector128_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__Or_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__Or_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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 Vector128<UInt32> _fld1;
+ public Vector128<UInt32> _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<Vector128<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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__Or_Vector128_UInt32 testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector128_UInt32 testClass)
+ {
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector128<UInt32> _clsVar1;
+ private static Vector128<UInt32> _clsVar2;
+
+ private Vector128<UInt32> _fld1;
+ private Vector128<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_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>>());
+ 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__Or_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 < 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.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.Or(
+ Unsafe.Read<Vector128<UInt32>>(_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.Or(
+ AdvSimd.LoadVector128((UInt32*)(_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.Or), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt32>>(_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.Or), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt32*)(_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.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector128((UInt32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector128_UInt32();
+ var result = AdvSimd.Or(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__Or_Vector128_UInt32();
+
+ fixed (Vector128<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((UInt32*)(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.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((UInt32*)(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.Or(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.Or(
+ AdvSimd.LoadVector128((UInt32*)(&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(Vector128<UInt32> op1, Vector128<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, 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];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<UInt32>(Vector128<UInt32>, 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 Or_Vector128_UInt64()
+ {
+ var test = new SimpleBinaryOpTest__Or_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__Or_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(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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<UInt64, 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 Vector128<UInt64> _fld1;
+ public Vector128<UInt64> _fld2;
+
+ 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>>());
+ 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__Or_Vector128_UInt64 testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector128_UInt64 testClass)
+ {
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((UInt64*)(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<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+ private static UInt64[] _data2 = new UInt64[Op2ElementCount];
+
+ private static Vector128<UInt64> _clsVar1;
+ private static Vector128<UInt64> _clsVar2;
+
+ private Vector128<UInt64> _fld1;
+ private Vector128<UInt64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_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>>());
+ 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__Or_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 < 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.GetUInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt64[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.Or(
+ Unsafe.Read<Vector128<UInt64>>(_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.Or(
+ AdvSimd.LoadVector128((UInt64*)(_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.Or), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(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.Or), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt64>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((UInt64*)(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<Vector128<UInt64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector128((UInt64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector128_UInt64();
+ var result = AdvSimd.Or(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__Or_Vector128_UInt64();
+
+ fixed (Vector128<UInt64>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((UInt64*)(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.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector128((UInt64*)(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.Or(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.Or(
+ AdvSimd.LoadVector128((UInt64*)(&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(Vector128<UInt64> op1, Vector128<UInt64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[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<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<UInt64>(Vector128<UInt64>, 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 Or_Vector64_Byte()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector64_Byte();
+
+ 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__Or_Vector64_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector64<Byte> _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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector64_Byte testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector64_Byte testClass)
+ {
+ fixed (Vector64<Byte>* pFld1 = &_fld1)
+ fixed (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector64<Byte> _clsVar1;
+ private static Vector64<Byte> _clsVar2;
+
+ private Vector64<Byte> _fld1;
+ private Vector64<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.Or(
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_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.Or(
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_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.Or), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Or), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _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 (Vector64<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector64((Byte*)(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<Vector64<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector64((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector64_Byte();
+ var result = AdvSimd.Or(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__Or_Vector64_Byte();
+
+ fixed (Vector64<Byte>* pFld1 = &test._fld1)
+ fixed (Vector64<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Or(_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 (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(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.Or(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.Or(
+ AdvSimd.LoadVector64((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector64((Byte*)(&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, Vector64<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[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<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<Byte>(Vector64<Byte>, Vector64<Byte>): {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 Or_Vector64_Double()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector64_Double();
+
+ 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__Or_Vector64_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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<Double> _fld1;
+ public Vector64<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector64_Double testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector64_Double testClass)
+ {
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector64<Double> _clsVar1;
+ private static Vector64<Double> _clsVar2;
+
+ private Vector64<Double> _fld1;
+ private Vector64<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector64_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector64_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[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.Or(
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_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.Or(
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_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.Or), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(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.Or), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Double*)(pClsVar1)),
+ AdvSimd.LoadVector64((Double*)(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<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector64_Double();
+ var result = AdvSimd.Or(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__Or_Vector64_Double();
+
+ fixed (Vector64<Double>* pFld1 = &test._fld1)
+ fixed (Vector64<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(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.Or(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.Or(
+ AdvSimd.LoadVector64((Double*)(&test._fld1)),
+ AdvSimd.LoadVector64((Double*)(&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<Double> op1, Vector64<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.Or(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<Double>(Vector64<Double>, Vector64<Double>): {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 Or_Vector64_Int16()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector64_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__Or_Vector64_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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<Int16> _fld1;
+ public Vector64<Int16> _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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector64_Int16 testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector64_Int16 testClass)
+ {
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ fixed (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((Int16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector64<Int16> _clsVar1;
+ private static Vector64<Int16> _clsVar2;
+
+ private Vector64<Int16> _fld1;
+ private Vector64<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Or(
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Or(
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Or), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Or), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _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 (Vector64<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Int16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector64((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector64_Int16();
+ var result = AdvSimd.Or(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__Or_Vector64_Int16();
+
+ fixed (Vector64<Int16>* pFld1 = &test._fld1)
+ fixed (Vector64<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Or(_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 (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Or(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.Or(
+ AdvSimd.LoadVector64((Int16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int16> op1, Vector64<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<Int16>(Vector64<Int16>, Vector64<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 Or_Vector64_Int32()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector64_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__Or_Vector64_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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<Int32> _fld1;
+ public Vector64<Int32> _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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref testStruct._fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector64_Int32 testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector64_Int32 testClass)
+ {
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ fixed (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((Int32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector64<Int32> _clsVar1;
+ private static Vector64<Int32> _clsVar2;
+
+ private Vector64<Int32> _fld1;
+ private Vector64<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Or(
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Or(
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Or), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Or), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _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 (Vector64<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Int32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector64((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector64_Int32();
+ var result = AdvSimd.Or(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__Or_Vector64_Int32();
+
+ fixed (Vector64<Int32>* pFld1 = &test._fld1)
+ fixed (Vector64<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Or(_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 (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Or(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.Or(
+ AdvSimd.LoadVector64((Int32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int32> op1, Vector64<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<Int32>(Vector64<Int32>, Vector64<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 Or_Vector64_Int64()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector64_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__Or_Vector64_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(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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<Int64, 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<Int64> _fld1;
+ public Vector64<Int64> _fld2;
+
+ 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<Vector64<Int64>, byte>(ref testStruct._fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref testStruct._fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector64_Int64 testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector64_Int64 testClass)
+ {
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ fixed (Vector64<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((Int64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+ private static Int64[] _data2 = new Int64[Op2ElementCount];
+
+ private static Vector64<Int64> _clsVar1;
+ private static Vector64<Int64> _clsVar2;
+
+ private Vector64<Int64> _fld1;
+ private Vector64<Int64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector64_Int64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector64_Int64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new Int64[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.Or(
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Or(
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Or), new Type[] { typeof(Vector64<Int64>), typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(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.Or), new Type[] { typeof(Vector64<Int64>), typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int64>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Int64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Int64*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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((Int64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector64_Int64();
+ var result = AdvSimd.Or(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__Or_Vector64_Int64();
+
+ fixed (Vector64<Int64>* pFld1 = &test._fld1)
+ fixed (Vector64<Int64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((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.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ fixed (Vector64<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((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.Or(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.Or(
+ AdvSimd.LoadVector64((Int64*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int64> op1, Vector64<Int64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<Int64>(Vector64<Int64>, Vector64<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 Or_Vector64_SByte()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector64_SByte();
+
+ 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__Or_Vector64_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector64<SByte> _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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector64_SByte testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector64_SByte testClass)
+ {
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ fixed (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector64<SByte> _clsVar1;
+ private static Vector64<SByte> _clsVar2;
+
+ private Vector64<SByte> _fld1;
+ private Vector64<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Or(
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_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.Or(
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_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.Or), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Or), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _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 (Vector64<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector64((SByte*)(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<Vector64<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector64((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector64_SByte();
+ var result = AdvSimd.Or(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__Or_Vector64_SByte();
+
+ fixed (Vector64<SByte>* pFld1 = &test._fld1)
+ fixed (Vector64<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Or(_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 (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(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.Or(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.Or(
+ AdvSimd.LoadVector64((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector64((SByte*)(&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, Vector64<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[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<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<SByte>(Vector64<SByte>, Vector64<SByte>): {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 Or_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector64_Single();
+
+ 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__Or_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector64_Single testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.Or(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.Or(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.Or), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(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.Or), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector64_Single();
+ var result = AdvSimd.Or(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__Or_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.Or(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.Or(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Or(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<Single>(Vector64<Single>, Vector64<Single>): {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 Or_Vector64_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector64_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__Or_Vector64_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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<UInt16> _fld1;
+ public Vector64<UInt16> _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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector64_UInt16 testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector64_UInt16 testClass)
+ {
+ fixed (Vector64<UInt16>* pFld1 = &_fld1)
+ fixed (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((UInt16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector64<UInt16> _clsVar1;
+ private static Vector64<UInt16> _clsVar2;
+
+ private Vector64<UInt16> _fld1;
+ private Vector64<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _clsVar2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.Or(
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Or(
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Or), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Or), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _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 (Vector64<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((UInt16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector64((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector64_UInt16();
+ var result = AdvSimd.Or(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__Or_Vector64_UInt16();
+
+ fixed (Vector64<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Or(_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 (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Or(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.Or(
+ AdvSimd.LoadVector64((UInt16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt16> op1, Vector64<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] left, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<UInt16>(Vector64<UInt16>, Vector64<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 Or_Vector64_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector64_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__Or_Vector64_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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<UInt32> _fld1;
+ public Vector64<UInt32> _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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector64_UInt32 testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector64_UInt32 testClass)
+ {
+ fixed (Vector64<UInt32>* pFld1 = &_fld1)
+ fixed (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((UInt32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector64<UInt32> _clsVar1;
+ private static Vector64<UInt32> _clsVar2;
+
+ private Vector64<UInt32> _fld1;
+ private Vector64<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _clsVar2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.Or(
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Or(
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Or), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Or), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _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 (Vector64<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((UInt32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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.LoadVector64((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector64_UInt32();
+ var result = AdvSimd.Or(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__Or_Vector64_UInt32();
+
+ fixed (Vector64<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Or(_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 (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Or(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.Or(
+ AdvSimd.LoadVector64((UInt32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt32> op1, Vector64<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] left, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<UInt32>(Vector64<UInt32>, Vector64<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 Or_Vector64_UInt64()
+ {
+ var test = new SimpleBinaryOpTest__Or_Vector64_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__Or_Vector64_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(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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<UInt64, 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<UInt64> _fld1;
+ public Vector64<UInt64> _fld2;
+
+ 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<Vector64<UInt64>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Or_Vector64_UInt64 testClass)
+ {
+ var result = AdvSimd.Or(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Or_Vector64_UInt64 testClass)
+ {
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ fixed (Vector64<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((UInt64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+ private static UInt64[] _data2 = new UInt64[Op2ElementCount];
+
+ private static Vector64<UInt64> _clsVar1;
+ private static Vector64<UInt64> _clsVar2;
+
+ private Vector64<UInt64> _fld1;
+ private Vector64<UInt64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Or_Vector64_UInt64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _clsVar1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _clsVar2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ }
+
+ public SimpleBinaryOpTest__Or_Vector64_UInt64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt64[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.Or(
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Or(
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Or), new Type[] { typeof(Vector64<UInt64>), typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(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.Or), new Type[] { typeof(Vector64<UInt64>), typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Or(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<UInt64>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<UInt64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((UInt64*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Or(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((UInt64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Or(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Or_Vector64_UInt64();
+ var result = AdvSimd.Or(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__Or_Vector64_UInt64();
+
+ fixed (Vector64<UInt64>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((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.Or(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ fixed (Vector64<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Or(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((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.Or(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.Or(
+ AdvSimd.LoadVector64((UInt64*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt64> op1, Vector64<UInt64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Or(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Or)}<UInt64>(Vector64<UInt64>, Vector64<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 OrNot_Vector128_Byte()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_Byte();
+
+ 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__OrNot_Vector128_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector128<Byte> _fld1;
+ public Vector128<Byte> _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<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector128_Byte testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector128_Byte testClass)
+ {
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector128<Byte> _clsVar1;
+ private static Vector128<Byte> _clsVar2;
+
+ private Vector128<Byte> _fld1;
+ private Vector128<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector128_Byte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector128_Byte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.OrNot(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.OrNot(
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.OrNot), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.OrNot), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Byte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector128((Byte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_Byte();
+ var result = AdvSimd.OrNot(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__OrNot_Vector128_Byte();
+
+ fixed (Vector128<Byte>* pFld1 = &test._fld1)
+ fixed (Vector128<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector128((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector128((Byte*)(&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(Vector128<Byte> op1, Vector128<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, 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];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ 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, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<Byte>(Vector128<Byte>, Vector128<Byte>): {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 OrNot_Vector128_Double()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_Double();
+
+ 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__OrNot_Vector128_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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 Vector128<Double> _fld1;
+ public Vector128<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector128_Double testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector128_Double testClass)
+ {
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+ private static Vector128<Double> _clsVar2;
+
+ private Vector128<Double> _fld1;
+ private Vector128<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector128_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector128_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[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.OrNot(
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_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.OrNot(
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_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.OrNot), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(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.OrNot), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Double*)(pClsVar1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_Double();
+ var result = AdvSimd.OrNot(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__OrNot_Vector128_Double();
+
+ fixed (Vector128<Double>* pFld1 = &test._fld1)
+ fixed (Vector128<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector128((Double*)(&test._fld1)),
+ AdvSimd.LoadVector128((Double*)(&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(Vector128<Double> op1, Vector128<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<Double>(Vector128<Double>, Vector128<Double>): {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 OrNot_Vector128_Int16()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_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__OrNot_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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 Vector128<Int16> _fld1;
+ public Vector128<Int16> _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<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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__OrNot_Vector128_Int16 testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector128_Int16 testClass)
+ {
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector128<Int16> _clsVar1;
+ private static Vector128<Int16> _clsVar2;
+
+ private Vector128<Int16> _fld1;
+ private Vector128<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_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>>());
+ 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__OrNot_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 < 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.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.OrNot(
+ Unsafe.Read<Vector128<Int16>>(_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.OrNot(
+ AdvSimd.LoadVector128((Int16*)(_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.OrNot), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int16>>(_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.OrNot), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int16*)(_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.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector128((Int16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_Int16();
+ var result = AdvSimd.OrNot(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__OrNot_Vector128_Int16();
+
+ fixed (Vector128<Int16>* pFld1 = &test._fld1)
+ fixed (Vector128<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Int16*)(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.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Int16*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector128((Int16*)(&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(Vector128<Int16> op1, Vector128<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, 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];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<Int16>(Vector128<Int16>, 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 OrNot_Vector128_Int32()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_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__OrNot_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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 Vector128<Int32> _fld1;
+ public Vector128<Int32> _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<Vector128<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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__OrNot_Vector128_Int32 testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector128_Int32 testClass)
+ {
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector128<Int32> _clsVar1;
+ private static Vector128<Int32> _clsVar2;
+
+ private Vector128<Int32> _fld1;
+ private Vector128<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_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>>());
+ 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__OrNot_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 < 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.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.OrNot(
+ Unsafe.Read<Vector128<Int32>>(_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.OrNot(
+ AdvSimd.LoadVector128((Int32*)(_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.OrNot), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int32>>(_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.OrNot), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int32*)(_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.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector128((Int32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_Int32();
+ var result = AdvSimd.OrNot(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__OrNot_Vector128_Int32();
+
+ fixed (Vector128<Int32>* pFld1 = &test._fld1)
+ fixed (Vector128<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Int32*)(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.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Int32*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector128((Int32*)(&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(Vector128<Int32> op1, Vector128<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, 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];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<Int32>(Vector128<Int32>, 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 OrNot_Vector128_Int64()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_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__OrNot_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(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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<Int64, 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 Vector128<Int64> _fld1;
+ public Vector128<Int64> _fld2;
+
+ 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>>());
+ 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__OrNot_Vector128_Int64 testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector128_Int64 testClass)
+ {
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Int64*)(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<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+ private static Int64[] _data2 = new Int64[Op2ElementCount];
+
+ private static Vector128<Int64> _clsVar1;
+ private static Vector128<Int64> _clsVar2;
+
+ private Vector128<Int64> _fld1;
+ private Vector128<Int64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_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>>());
+ 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__OrNot_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 < 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.GetInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new Int64[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.OrNot(
+ Unsafe.Read<Vector128<Int64>>(_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.OrNot(
+ AdvSimd.LoadVector128((Int64*)(_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.OrNot), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(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.OrNot), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int64>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Int64*)(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<Vector128<Int64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector128((Int64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_Int64();
+ var result = AdvSimd.OrNot(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__OrNot_Vector128_Int64();
+
+ fixed (Vector128<Int64>* pFld1 = &test._fld1)
+ fixed (Vector128<Int64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Int64*)(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.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Int64*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector128((Int64*)(&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(Vector128<Int64> op1, Vector128<Int64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[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<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<Int64>(Vector128<Int64>, 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 OrNot_Vector128_SByte()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_SByte();
+
+ 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__OrNot_Vector128_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector128<SByte> _fld1;
+ public Vector128<SByte> _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<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector128_SByte testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector128_SByte testClass)
+ {
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector128<SByte> _clsVar1;
+ private static Vector128<SByte> _clsVar2;
+
+ private Vector128<SByte> _fld1;
+ private Vector128<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector128_SByte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector128_SByte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.OrNot(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.OrNot(
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.OrNot), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.OrNot), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_SByte();
+ var result = AdvSimd.OrNot(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__OrNot_Vector128_SByte();
+
+ fixed (Vector128<SByte>* pFld1 = &test._fld1)
+ fixed (Vector128<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector128((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector128((SByte*)(&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(Vector128<SByte> op1, Vector128<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, 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];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ 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, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<SByte>(Vector128<SByte>, Vector128<SByte>): {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 OrNot_Vector128_Single()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_Single();
+
+ 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__OrNot_Vector128_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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 Vector128<Single> _fld1;
+ public Vector128<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector128_Single testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector128_Single testClass)
+ {
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector128_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector128_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.OrNot(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_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.OrNot(
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_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.OrNot), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(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.OrNot), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Single*)(pClsVar1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_Single();
+ var result = AdvSimd.OrNot(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__OrNot_Vector128_Single();
+
+ fixed (Vector128<Single>* pFld1 = &test._fld1)
+ fixed (Vector128<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector128((Single*)(&test._fld1)),
+ AdvSimd.LoadVector128((Single*)(&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(Vector128<Single> op1, Vector128<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<Single>(Vector128<Single>, Vector128<Single>): {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 OrNot_Vector128_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_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__OrNot_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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 Vector128<UInt16> _fld1;
+ public Vector128<UInt16> _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<Vector128<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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__OrNot_Vector128_UInt16 testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector128_UInt16 testClass)
+ {
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector128<UInt16> _clsVar1;
+ private static Vector128<UInt16> _clsVar2;
+
+ private Vector128<UInt16> _fld1;
+ private Vector128<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_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>>());
+ 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__OrNot_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 < 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.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.OrNot(
+ Unsafe.Read<Vector128<UInt16>>(_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.OrNot(
+ AdvSimd.LoadVector128((UInt16*)(_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.OrNot), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt16>>(_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.OrNot), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt16*)(_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.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector128((UInt16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_UInt16();
+ var result = AdvSimd.OrNot(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__OrNot_Vector128_UInt16();
+
+ fixed (Vector128<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((UInt16*)(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.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((UInt16*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector128((UInt16*)(&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(Vector128<UInt16> op1, Vector128<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, 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];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<UInt16>(Vector128<UInt16>, 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 OrNot_Vector128_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_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__OrNot_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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 Vector128<UInt32> _fld1;
+ public Vector128<UInt32> _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<Vector128<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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__OrNot_Vector128_UInt32 testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector128_UInt32 testClass)
+ {
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector128<UInt32> _clsVar1;
+ private static Vector128<UInt32> _clsVar2;
+
+ private Vector128<UInt32> _fld1;
+ private Vector128<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_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>>());
+ 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__OrNot_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 < 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.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.OrNot(
+ Unsafe.Read<Vector128<UInt32>>(_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.OrNot(
+ AdvSimd.LoadVector128((UInt32*)(_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.OrNot), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt32>>(_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.OrNot), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt32*)(_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.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector128((UInt32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_UInt32();
+ var result = AdvSimd.OrNot(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__OrNot_Vector128_UInt32();
+
+ fixed (Vector128<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((UInt32*)(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.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((UInt32*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector128((UInt32*)(&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(Vector128<UInt32> op1, Vector128<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, 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];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<UInt32>(Vector128<UInt32>, 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 OrNot_Vector128_UInt64()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_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__OrNot_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(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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<UInt64, 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 Vector128<UInt64> _fld1;
+ public Vector128<UInt64> _fld2;
+
+ 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>>());
+ 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__OrNot_Vector128_UInt64 testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector128_UInt64 testClass)
+ {
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((UInt64*)(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<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+ private static UInt64[] _data2 = new UInt64[Op2ElementCount];
+
+ private static Vector128<UInt64> _clsVar1;
+ private static Vector128<UInt64> _clsVar2;
+
+ private Vector128<UInt64> _fld1;
+ private Vector128<UInt64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_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>>());
+ 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__OrNot_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 < 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.GetUInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt64[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.OrNot(
+ Unsafe.Read<Vector128<UInt64>>(_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.OrNot(
+ AdvSimd.LoadVector128((UInt64*)(_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.OrNot), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(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.OrNot), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt64>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((UInt64*)(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<Vector128<UInt64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector128((UInt64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector128_UInt64();
+ var result = AdvSimd.OrNot(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__OrNot_Vector128_UInt64();
+
+ fixed (Vector128<UInt64>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((UInt64*)(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.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector128((UInt64*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector128((UInt64*)(&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(Vector128<UInt64> op1, Vector128<UInt64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[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<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<UInt64>(Vector128<UInt64>, 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 OrNot_Vector64_Byte()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_Byte();
+
+ 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__OrNot_Vector64_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector64<Byte> _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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector64_Byte testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector64_Byte testClass)
+ {
+ fixed (Vector64<Byte>* pFld1 = &_fld1)
+ fixed (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector64<Byte> _clsVar1;
+ private static Vector64<Byte> _clsVar2;
+
+ private Vector64<Byte> _fld1;
+ private Vector64<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.OrNot(
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_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.OrNot(
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_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.OrNot), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.OrNot), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _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 (Vector64<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector64((Byte*)(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<Vector64<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector64((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_Byte();
+ var result = AdvSimd.OrNot(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__OrNot_Vector64_Byte();
+
+ fixed (Vector64<Byte>* pFld1 = &test._fld1)
+ fixed (Vector64<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.OrNot(_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 (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector64((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector64((Byte*)(&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, Vector64<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[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<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<Byte>(Vector64<Byte>, Vector64<Byte>): {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 OrNot_Vector64_Double()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_Double();
+
+ 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__OrNot_Vector64_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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<Double> _fld1;
+ public Vector64<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector64_Double testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector64_Double testClass)
+ {
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector64<Double> _clsVar1;
+ private static Vector64<Double> _clsVar2;
+
+ private Vector64<Double> _fld1;
+ private Vector64<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector64_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector64_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[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.OrNot(
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_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.OrNot(
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_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.OrNot), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(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.OrNot), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Double*)(pClsVar1)),
+ AdvSimd.LoadVector64((Double*)(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<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_Double();
+ var result = AdvSimd.OrNot(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__OrNot_Vector64_Double();
+
+ fixed (Vector64<Double>* pFld1 = &test._fld1)
+ fixed (Vector64<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector64((Double*)(&test._fld1)),
+ AdvSimd.LoadVector64((Double*)(&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<Double> op1, Vector64<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<Double>(Vector64<Double>, Vector64<Double>): {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 OrNot_Vector64_Int16()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_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__OrNot_Vector64_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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<Int16> _fld1;
+ public Vector64<Int16> _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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector64_Int16 testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector64_Int16 testClass)
+ {
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ fixed (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((Int16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector64<Int16> _clsVar1;
+ private static Vector64<Int16> _clsVar2;
+
+ private Vector64<Int16> _fld1;
+ private Vector64<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.OrNot(
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.OrNot(
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.OrNot), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.OrNot), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _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 (Vector64<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Int16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector64((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_Int16();
+ var result = AdvSimd.OrNot(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__OrNot_Vector64_Int16();
+
+ fixed (Vector64<Int16>* pFld1 = &test._fld1)
+ fixed (Vector64<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.OrNot(_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 (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.OrNot(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.OrNot(
+ AdvSimd.LoadVector64((Int16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int16> op1, Vector64<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<Int16>(Vector64<Int16>, Vector64<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 OrNot_Vector64_Int32()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_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__OrNot_Vector64_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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<Int32> _fld1;
+ public Vector64<Int32> _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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref testStruct._fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector64_Int32 testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector64_Int32 testClass)
+ {
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ fixed (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((Int32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector64<Int32> _clsVar1;
+ private static Vector64<Int32> _clsVar2;
+
+ private Vector64<Int32> _fld1;
+ private Vector64<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.OrNot(
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.OrNot(
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.OrNot), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.OrNot), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _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 (Vector64<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Int32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector64((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_Int32();
+ var result = AdvSimd.OrNot(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__OrNot_Vector64_Int32();
+
+ fixed (Vector64<Int32>* pFld1 = &test._fld1)
+ fixed (Vector64<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.OrNot(_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 (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.OrNot(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.OrNot(
+ AdvSimd.LoadVector64((Int32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int32> op1, Vector64<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<Int32>(Vector64<Int32>, Vector64<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 OrNot_Vector64_Int64()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_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__OrNot_Vector64_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(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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<Int64, 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<Int64> _fld1;
+ public Vector64<Int64> _fld2;
+
+ 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<Vector64<Int64>, byte>(ref testStruct._fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref testStruct._fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector64_Int64 testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector64_Int64 testClass)
+ {
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ fixed (Vector64<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((Int64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+ private static Int64[] _data2 = new Int64[Op2ElementCount];
+
+ private static Vector64<Int64> _clsVar1;
+ private static Vector64<Int64> _clsVar2;
+
+ private Vector64<Int64> _fld1;
+ private Vector64<Int64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector64_Int64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector64_Int64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new Int64[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.OrNot(
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.OrNot(
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.OrNot), new Type[] { typeof(Vector64<Int64>), typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(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.OrNot), new Type[] { typeof(Vector64<Int64>), typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int64>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Int64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Int64*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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((Int64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_Int64();
+ var result = AdvSimd.OrNot(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__OrNot_Vector64_Int64();
+
+ fixed (Vector64<Int64>* pFld1 = &test._fld1)
+ fixed (Vector64<Int64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((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.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ fixed (Vector64<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((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.OrNot(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.OrNot(
+ AdvSimd.LoadVector64((Int64*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int64> op1, Vector64<Int64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<Int64>(Vector64<Int64>, Vector64<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 OrNot_Vector64_SByte()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_SByte();
+
+ 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__OrNot_Vector64_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector64<SByte> _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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector64_SByte testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector64_SByte testClass)
+ {
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ fixed (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector64<SByte> _clsVar1;
+ private static Vector64<SByte> _clsVar2;
+
+ private Vector64<SByte> _fld1;
+ private Vector64<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.OrNot(
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_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.OrNot(
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_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.OrNot), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.OrNot), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _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 (Vector64<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector64((SByte*)(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<Vector64<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector64((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_SByte();
+ var result = AdvSimd.OrNot(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__OrNot_Vector64_SByte();
+
+ fixed (Vector64<SByte>* pFld1 = &test._fld1)
+ fixed (Vector64<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.OrNot(_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 (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector64((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector64((SByte*)(&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, Vector64<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[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<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<SByte>(Vector64<SByte>, Vector64<SByte>): {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 OrNot_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_Single();
+
+ 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__OrNot_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector64_Single testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.OrNot(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.OrNot(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.OrNot), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(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.OrNot), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_Single();
+ var result = AdvSimd.OrNot(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__OrNot_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.OrNot(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.OrNot(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<Single>(Vector64<Single>, Vector64<Single>): {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 OrNot_Vector64_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_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__OrNot_Vector64_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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<UInt16> _fld1;
+ public Vector64<UInt16> _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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector64_UInt16 testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector64_UInt16 testClass)
+ {
+ fixed (Vector64<UInt16>* pFld1 = &_fld1)
+ fixed (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((UInt16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector64<UInt16> _clsVar1;
+ private static Vector64<UInt16> _clsVar2;
+
+ private Vector64<UInt16> _fld1;
+ private Vector64<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _clsVar2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.OrNot(
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.OrNot(
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.OrNot), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.OrNot), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _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 (Vector64<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((UInt16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector64((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_UInt16();
+ var result = AdvSimd.OrNot(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__OrNot_Vector64_UInt16();
+
+ fixed (Vector64<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.OrNot(_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 (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.OrNot(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.OrNot(
+ AdvSimd.LoadVector64((UInt16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt16> op1, Vector64<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] left, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<UInt16>(Vector64<UInt16>, Vector64<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 OrNot_Vector64_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_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__OrNot_Vector64_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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<UInt32> _fld1;
+ public Vector64<UInt32> _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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector64_UInt32 testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector64_UInt32 testClass)
+ {
+ fixed (Vector64<UInt32>* pFld1 = &_fld1)
+ fixed (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((UInt32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector64<UInt32> _clsVar1;
+ private static Vector64<UInt32> _clsVar2;
+
+ private Vector64<UInt32> _fld1;
+ private Vector64<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _clsVar2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.OrNot(
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.OrNot(
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.OrNot), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.OrNot), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _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 (Vector64<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((UInt32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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.LoadVector64((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_UInt32();
+ var result = AdvSimd.OrNot(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__OrNot_Vector64_UInt32();
+
+ fixed (Vector64<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.OrNot(_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 (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.OrNot(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.OrNot(
+ AdvSimd.LoadVector64((UInt32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt32> op1, Vector64<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] left, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<UInt32>(Vector64<UInt32>, Vector64<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 OrNot_Vector64_UInt64()
+ {
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_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__OrNot_Vector64_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(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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<UInt64, 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<UInt64> _fld1;
+ public Vector64<UInt64> _fld2;
+
+ 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<Vector64<UInt64>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__OrNot_Vector64_UInt64 testClass)
+ {
+ var result = AdvSimd.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__OrNot_Vector64_UInt64 testClass)
+ {
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ fixed (Vector64<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((UInt64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+ private static UInt64[] _data2 = new UInt64[Op2ElementCount];
+
+ private static Vector64<UInt64> _clsVar1;
+ private static Vector64<UInt64> _clsVar2;
+
+ private Vector64<UInt64> _fld1;
+ private Vector64<UInt64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__OrNot_Vector64_UInt64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _clsVar1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _clsVar2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ }
+
+ public SimpleBinaryOpTest__OrNot_Vector64_UInt64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt64[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.OrNot(
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.OrNot(
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.OrNot), new Type[] { typeof(Vector64<UInt64>), typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(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.OrNot), new Type[] { typeof(Vector64<UInt64>), typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.OrNot(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<UInt64>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<UInt64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((UInt64*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.OrNot(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((UInt64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.OrNot(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__OrNot_Vector64_UInt64();
+ var result = AdvSimd.OrNot(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__OrNot_Vector64_UInt64();
+
+ fixed (Vector64<UInt64>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((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.OrNot(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ fixed (Vector64<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.OrNot(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((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.OrNot(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.OrNot(
+ AdvSimd.LoadVector64((UInt64*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt64> op1, Vector64<UInt64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.OrNot(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.OrNot)}<UInt64>(Vector64<UInt64>, Vector64<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;
+ }
+ }
+ }
+}
["AddScalar.Vector64.Int64"] = AddScalar_Vector64_Int64,
["AddScalar.Vector64.Single"] = AddScalar_Vector64_Single,
["AddScalar.Vector64.UInt64"] = AddScalar_Vector64_UInt64,
+ ["And.Vector64.Byte"] = And_Vector64_Byte,
+ ["And.Vector64.Double"] = And_Vector64_Double,
+ ["And.Vector64.Int16"] = And_Vector64_Int16,
+ ["And.Vector64.Int32"] = And_Vector64_Int32,
+ ["And.Vector64.Int64"] = And_Vector64_Int64,
+ ["And.Vector64.SByte"] = And_Vector64_SByte,
+ ["And.Vector64.Single"] = And_Vector64_Single,
+ ["And.Vector64.UInt16"] = And_Vector64_UInt16,
+ ["And.Vector64.UInt32"] = And_Vector64_UInt32,
+ ["And.Vector64.UInt64"] = And_Vector64_UInt64,
+ ["And.Vector128.Byte"] = And_Vector128_Byte,
+ ["And.Vector128.Double"] = And_Vector128_Double,
+ ["And.Vector128.Int16"] = And_Vector128_Int16,
+ ["And.Vector128.Int32"] = And_Vector128_Int32,
+ ["And.Vector128.Int64"] = And_Vector128_Int64,
+ ["And.Vector128.SByte"] = And_Vector128_SByte,
+ ["And.Vector128.Single"] = And_Vector128_Single,
+ ["And.Vector128.UInt16"] = And_Vector128_UInt16,
+ ["And.Vector128.UInt32"] = And_Vector128_UInt32,
+ ["And.Vector128.UInt64"] = And_Vector128_UInt64,
+ ["BitwiseClear.Vector64.Byte"] = BitwiseClear_Vector64_Byte,
+ ["BitwiseClear.Vector64.Double"] = BitwiseClear_Vector64_Double,
+ ["BitwiseClear.Vector64.Int16"] = BitwiseClear_Vector64_Int16,
+ ["BitwiseClear.Vector64.Int32"] = BitwiseClear_Vector64_Int32,
+ ["BitwiseClear.Vector64.Int64"] = BitwiseClear_Vector64_Int64,
+ ["BitwiseClear.Vector64.SByte"] = BitwiseClear_Vector64_SByte,
+ ["BitwiseClear.Vector64.Single"] = BitwiseClear_Vector64_Single,
+ ["BitwiseClear.Vector64.UInt16"] = BitwiseClear_Vector64_UInt16,
+ ["BitwiseClear.Vector64.UInt32"] = BitwiseClear_Vector64_UInt32,
+ ["BitwiseClear.Vector64.UInt64"] = BitwiseClear_Vector64_UInt64,
+ ["BitwiseClear.Vector128.Byte"] = BitwiseClear_Vector128_Byte,
+ ["BitwiseClear.Vector128.Double"] = BitwiseClear_Vector128_Double,
+ ["BitwiseClear.Vector128.Int16"] = BitwiseClear_Vector128_Int16,
+ ["BitwiseClear.Vector128.Int32"] = BitwiseClear_Vector128_Int32,
+ ["BitwiseClear.Vector128.Int64"] = BitwiseClear_Vector128_Int64,
+ ["BitwiseClear.Vector128.SByte"] = BitwiseClear_Vector128_SByte,
+ ["BitwiseClear.Vector128.Single"] = BitwiseClear_Vector128_Single,
+ ["BitwiseClear.Vector128.UInt16"] = BitwiseClear_Vector128_UInt16,
+ ["BitwiseClear.Vector128.UInt32"] = BitwiseClear_Vector128_UInt32,
+ ["BitwiseClear.Vector128.UInt64"] = BitwiseClear_Vector128_UInt64,
["BitwiseSelect.Vector64.Byte"] = BitwiseSelect_Vector64_Byte,
["BitwiseSelect.Vector64.Double"] = BitwiseSelect_Vector64_Double,
["BitwiseSelect.Vector64.Int16"] = BitwiseSelect_Vector64_Int16,
["CompareTest.Vector128.Single"] = CompareTest_Vector128_Single,
["CompareTest.Vector128.UInt16"] = CompareTest_Vector128_UInt16,
["CompareTest.Vector128.UInt32"] = CompareTest_Vector128_UInt32,
+ ["DivideScalar.Vector64.Double"] = DivideScalar_Vector64_Double,
+ ["DivideScalar.Vector64.Single"] = DivideScalar_Vector64_Single,
["LeadingSignCount.Vector64.Int16"] = LeadingSignCount_Vector64_Int16,
["LeadingSignCount.Vector64.Int32"] = LeadingSignCount_Vector64_Int32,
["LeadingSignCount.Vector64.SByte"] = LeadingSignCount_Vector64_SByte,
["LoadVector128.UInt16"] = LoadVector128_UInt16,
["LoadVector128.UInt32"] = LoadVector128_UInt32,
["LoadVector128.UInt64"] = LoadVector128_UInt64,
+ ["Max.Vector64.Byte"] = Max_Vector64_Byte,
+ ["Max.Vector64.Int16"] = Max_Vector64_Int16,
+ ["Max.Vector64.Int32"] = Max_Vector64_Int32,
+ ["Max.Vector64.SByte"] = Max_Vector64_SByte,
+ ["Max.Vector64.Single"] = Max_Vector64_Single,
+ ["Max.Vector64.UInt16"] = Max_Vector64_UInt16,
+ ["Max.Vector64.UInt32"] = Max_Vector64_UInt32,
+ ["Max.Vector128.Byte"] = Max_Vector128_Byte,
+ ["Max.Vector128.Int16"] = Max_Vector128_Int16,
+ ["Max.Vector128.Int32"] = Max_Vector128_Int32,
+ ["Max.Vector128.SByte"] = Max_Vector128_SByte,
+ ["Max.Vector128.Single"] = Max_Vector128_Single,
+ ["Max.Vector128.UInt16"] = Max_Vector128_UInt16,
+ ["Max.Vector128.UInt32"] = Max_Vector128_UInt32,
+ ["Min.Vector64.Byte"] = Min_Vector64_Byte,
+ ["Min.Vector64.Int16"] = Min_Vector64_Int16,
+ ["Min.Vector64.Int32"] = Min_Vector64_Int32,
+ ["Min.Vector64.SByte"] = Min_Vector64_SByte,
+ ["Min.Vector64.Single"] = Min_Vector64_Single,
+ ["Min.Vector64.UInt16"] = Min_Vector64_UInt16,
+ ["Min.Vector64.UInt32"] = Min_Vector64_UInt32,
+ ["Min.Vector128.Byte"] = Min_Vector128_Byte,
+ ["Min.Vector128.Int16"] = Min_Vector128_Int16,
+ ["Min.Vector128.Int32"] = Min_Vector128_Int32,
+ ["Min.Vector128.SByte"] = Min_Vector128_SByte,
+ ["Min.Vector128.Single"] = Min_Vector128_Single,
+ ["Min.Vector128.UInt16"] = Min_Vector128_UInt16,
+ ["Min.Vector128.UInt32"] = Min_Vector128_UInt32,
+ ["Multiply.Vector64.Byte"] = Multiply_Vector64_Byte,
+ ["Multiply.Vector64.Int16"] = Multiply_Vector64_Int16,
+ ["Multiply.Vector64.Int32"] = Multiply_Vector64_Int32,
+ ["Multiply.Vector64.SByte"] = Multiply_Vector64_SByte,
+ ["Multiply.Vector64.Single"] = Multiply_Vector64_Single,
+ ["Multiply.Vector64.UInt16"] = Multiply_Vector64_UInt16,
+ ["Multiply.Vector64.UInt32"] = Multiply_Vector64_UInt32,
+ ["Multiply.Vector128.Byte"] = Multiply_Vector128_Byte,
+ ["Multiply.Vector128.Int16"] = Multiply_Vector128_Int16,
+ ["Multiply.Vector128.Int32"] = Multiply_Vector128_Int32,
+ ["Multiply.Vector128.SByte"] = Multiply_Vector128_SByte,
+ ["Multiply.Vector128.Single"] = Multiply_Vector128_Single,
+ ["Multiply.Vector128.UInt16"] = Multiply_Vector128_UInt16,
+ ["Multiply.Vector128.UInt32"] = Multiply_Vector128_UInt32,
+ ["MultiplyScalar.Vector64.Double"] = MultiplyScalar_Vector64_Double,
+ ["MultiplyScalar.Vector64.Single"] = MultiplyScalar_Vector64_Single,
+ ["Negate.Vector64.Int16"] = Negate_Vector64_Int16,
+ ["Negate.Vector64.Int32"] = Negate_Vector64_Int32,
+ ["Negate.Vector64.SByte"] = Negate_Vector64_SByte,
+ ["Negate.Vector64.Single"] = Negate_Vector64_Single,
+ ["Negate.Vector128.Int16"] = Negate_Vector128_Int16,
+ ["Negate.Vector128.Int32"] = Negate_Vector128_Int32,
+ ["Negate.Vector128.SByte"] = Negate_Vector128_SByte,
+ ["Negate.Vector128.Single"] = Negate_Vector128_Single,
+ ["NegateScalar.Vector64.Double"] = NegateScalar_Vector64_Double,
+ ["NegateScalar.Vector64.Single"] = NegateScalar_Vector64_Single,
+ ["Not.Vector64.Byte"] = Not_Vector64_Byte,
+ ["Not.Vector64.Double"] = Not_Vector64_Double,
+ ["Not.Vector64.Int16"] = Not_Vector64_Int16,
+ ["Not.Vector64.Int32"] = Not_Vector64_Int32,
+ ["Not.Vector64.Int64"] = Not_Vector64_Int64,
+ ["Not.Vector64.SByte"] = Not_Vector64_SByte,
+ ["Not.Vector64.Single"] = Not_Vector64_Single,
+ ["Not.Vector64.UInt16"] = Not_Vector64_UInt16,
+ ["Not.Vector64.UInt32"] = Not_Vector64_UInt32,
+ ["Not.Vector64.UInt64"] = Not_Vector64_UInt64,
+ ["Not.Vector128.Byte"] = Not_Vector128_Byte,
+ ["Not.Vector128.Double"] = Not_Vector128_Double,
+ ["Not.Vector128.Int16"] = Not_Vector128_Int16,
+ ["Not.Vector128.Int32"] = Not_Vector128_Int32,
+ ["Not.Vector128.Int64"] = Not_Vector128_Int64,
+ ["Not.Vector128.SByte"] = Not_Vector128_SByte,
+ ["Not.Vector128.Single"] = Not_Vector128_Single,
+ ["Not.Vector128.UInt16"] = Not_Vector128_UInt16,
+ ["Not.Vector128.UInt32"] = Not_Vector128_UInt32,
+ ["Not.Vector128.UInt64"] = Not_Vector128_UInt64,
+ ["Or.Vector64.Byte"] = Or_Vector64_Byte,
+ ["Or.Vector64.Double"] = Or_Vector64_Double,
+ ["Or.Vector64.Int16"] = Or_Vector64_Int16,
+ ["Or.Vector64.Int32"] = Or_Vector64_Int32,
+ ["Or.Vector64.Int64"] = Or_Vector64_Int64,
+ ["Or.Vector64.SByte"] = Or_Vector64_SByte,
+ ["Or.Vector64.Single"] = Or_Vector64_Single,
+ ["Or.Vector64.UInt16"] = Or_Vector64_UInt16,
+ ["Or.Vector64.UInt32"] = Or_Vector64_UInt32,
+ ["Or.Vector64.UInt64"] = Or_Vector64_UInt64,
+ ["Or.Vector128.Byte"] = Or_Vector128_Byte,
+ ["Or.Vector128.Double"] = Or_Vector128_Double,
+ ["Or.Vector128.Int16"] = Or_Vector128_Int16,
+ ["Or.Vector128.Int32"] = Or_Vector128_Int32,
+ ["Or.Vector128.Int64"] = Or_Vector128_Int64,
+ ["Or.Vector128.SByte"] = Or_Vector128_SByte,
+ ["Or.Vector128.Single"] = Or_Vector128_Single,
+ ["Or.Vector128.UInt16"] = Or_Vector128_UInt16,
+ ["Or.Vector128.UInt32"] = Or_Vector128_UInt32,
+ ["Or.Vector128.UInt64"] = Or_Vector128_UInt64,
+ ["OrNot.Vector64.Byte"] = OrNot_Vector64_Byte,
+ ["OrNot.Vector64.Double"] = OrNot_Vector64_Double,
+ ["OrNot.Vector64.Int16"] = OrNot_Vector64_Int16,
+ ["OrNot.Vector64.Int32"] = OrNot_Vector64_Int32,
+ ["OrNot.Vector64.Int64"] = OrNot_Vector64_Int64,
+ ["OrNot.Vector64.SByte"] = OrNot_Vector64_SByte,
+ ["OrNot.Vector64.Single"] = OrNot_Vector64_Single,
+ ["OrNot.Vector64.UInt16"] = OrNot_Vector64_UInt16,
+ ["OrNot.Vector64.UInt32"] = OrNot_Vector64_UInt32,
+ ["OrNot.Vector64.UInt64"] = OrNot_Vector64_UInt64,
+ ["OrNot.Vector128.Byte"] = OrNot_Vector128_Byte,
+ ["OrNot.Vector128.Double"] = OrNot_Vector128_Double,
+ ["OrNot.Vector128.Int16"] = OrNot_Vector128_Int16,
+ ["OrNot.Vector128.Int32"] = OrNot_Vector128_Int32,
+ ["OrNot.Vector128.Int64"] = OrNot_Vector128_Int64,
+ ["OrNot.Vector128.SByte"] = OrNot_Vector128_SByte,
+ ["OrNot.Vector128.Single"] = OrNot_Vector128_Single,
+ ["OrNot.Vector128.UInt16"] = OrNot_Vector128_UInt16,
+ ["OrNot.Vector128.UInt32"] = OrNot_Vector128_UInt32,
+ ["OrNot.Vector128.UInt64"] = OrNot_Vector128_UInt64,
["PopCount.Vector64.Byte"] = PopCount_Vector64_Byte,
["PopCount.Vector64.SByte"] = PopCount_Vector64_SByte,
["PopCount.Vector128.Byte"] = PopCount_Vector128_Byte,
["PopCount.Vector128.SByte"] = PopCount_Vector128_SByte,
+ ["SqrtScalar.Vector64.Double"] = SqrtScalar_Vector64_Double,
+ ["SqrtScalar.Vector64.Single"] = SqrtScalar_Vector64_Single,
+ ["Subtract.Vector64.Byte"] = Subtract_Vector64_Byte,
+ ["Subtract.Vector64.Int16"] = Subtract_Vector64_Int16,
+ ["Subtract.Vector64.Int32"] = Subtract_Vector64_Int32,
+ ["Subtract.Vector64.SByte"] = Subtract_Vector64_SByte,
+ ["Subtract.Vector64.Single"] = Subtract_Vector64_Single,
+ ["Subtract.Vector64.UInt16"] = Subtract_Vector64_UInt16,
+ ["Subtract.Vector64.UInt32"] = Subtract_Vector64_UInt32,
+ ["Subtract.Vector128.Byte"] = Subtract_Vector128_Byte,
+ ["Subtract.Vector128.Int16"] = Subtract_Vector128_Int16,
+ ["Subtract.Vector128.Int32"] = Subtract_Vector128_Int32,
+ ["Subtract.Vector128.Int64"] = Subtract_Vector128_Int64,
+ ["Subtract.Vector128.SByte"] = Subtract_Vector128_SByte,
+ ["Subtract.Vector128.Single"] = Subtract_Vector128_Single,
+ ["Subtract.Vector128.UInt16"] = Subtract_Vector128_UInt16,
+ ["Subtract.Vector128.UInt32"] = Subtract_Vector128_UInt32,
+ ["Subtract.Vector128.UInt64"] = Subtract_Vector128_UInt64,
+ ["SubtractScalar.Vector64.Double"] = SubtractScalar_Vector64_Double,
+ ["SubtractScalar.Vector64.Int64"] = SubtractScalar_Vector64_Int64,
+ ["SubtractScalar.Vector64.Single"] = SubtractScalar_Vector64_Single,
+ ["SubtractScalar.Vector64.UInt64"] = SubtractScalar_Vector64_UInt64,
+ ["Xor.Vector64.Byte"] = Xor_Vector64_Byte,
+ ["Xor.Vector64.Double"] = Xor_Vector64_Double,
+ ["Xor.Vector64.Int16"] = Xor_Vector64_Int16,
+ ["Xor.Vector64.Int32"] = Xor_Vector64_Int32,
+ ["Xor.Vector64.Int64"] = Xor_Vector64_Int64,
+ ["Xor.Vector64.SByte"] = Xor_Vector64_SByte,
+ ["Xor.Vector64.Single"] = Xor_Vector64_Single,
+ ["Xor.Vector64.UInt16"] = Xor_Vector64_UInt16,
+ ["Xor.Vector64.UInt32"] = Xor_Vector64_UInt32,
+ ["Xor.Vector64.UInt64"] = Xor_Vector64_UInt64,
+ ["Xor.Vector128.Byte"] = Xor_Vector128_Byte,
+ ["Xor.Vector128.Double"] = Xor_Vector128_Double,
+ ["Xor.Vector128.Int16"] = Xor_Vector128_Int16,
+ ["Xor.Vector128.Int32"] = Xor_Vector128_Int32,
+ ["Xor.Vector128.Int64"] = Xor_Vector128_Int64,
+ ["Xor.Vector128.SByte"] = Xor_Vector128_SByte,
+ ["Xor.Vector128.Single"] = Xor_Vector128_Single,
+ ["Xor.Vector128.UInt16"] = Xor_Vector128_UInt16,
+ ["Xor.Vector128.UInt32"] = Xor_Vector128_UInt32,
+ ["Xor.Vector128.UInt64"] = Xor_Vector128_UInt64,
};
}
}
--- /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 SqrtScalar_Vector64_Double()
+ {
+ var test = new SimpleUnaryOpTest__SqrtScalar_Vector64_Double();
+
+ 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__SqrtScalar_Vector64_Double
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Double[] inArray1, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, 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 Vector64<Double> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__SqrtScalar_Vector64_Double testClass)
+ {
+ var result = AdvSimd.SqrtScalar(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__SqrtScalar_Vector64_Double testClass)
+ {
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.SqrtScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+
+ private static Vector64<Double> _clsVar1;
+
+ private Vector64<Double> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__SqrtScalar_Vector64_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ }
+
+ public SimpleUnaryOpTest__SqrtScalar_Vector64_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, new Double[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.SqrtScalar(
+ Unsafe.Read<Vector64<Double>>(_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.SqrtScalar(
+ AdvSimd.LoadVector64((Double*)(_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.SqrtScalar), new Type[] { typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SqrtScalar), new Type[] { typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.SqrtScalar(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Double>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.SqrtScalar(
+ AdvSimd.LoadVector64((Double*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.SqrtScalar(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.SqrtScalar(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__SqrtScalar_Vector64_Double();
+ var result = AdvSimd.SqrtScalar(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__SqrtScalar_Vector64_Double();
+
+ fixed (Vector64<Double>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.SqrtScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.SqrtScalar(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.SqrtScalar(
+ AdvSimd.LoadVector64((Double*)(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.SqrtScalar(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.SqrtScalar(
+ AdvSimd.LoadVector64((Double*)(&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(Vector64<Double> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Double[] firstOp, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(Helpers.Sqrt(firstOp[0])) != BitConverter.DoubleToInt64Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SqrtScalar)}<Double>(Vector64<Double>): {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 SqrtScalar_Vector64_Single()
+ {
+ var test = new SimpleUnaryOpTest__SqrtScalar_Vector64_Single();
+
+ 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__SqrtScalar_Vector64_Single
+ {
+ private struct DataTable
+ {
+ private byte[] inArray1;
+ private byte[] outArray;
+
+ private GCHandle inHandle1;
+ private GCHandle outHandle;
+
+ private ulong alignment;
+
+ public DataTable(Single[] inArray1, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, 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 Vector64<Single> _fld1;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleUnaryOpTest__SqrtScalar_Vector64_Single testClass)
+ {
+ var result = AdvSimd.SqrtScalar(_fld1);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleUnaryOpTest__SqrtScalar_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.SqrtScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+
+ private Vector64<Single> _fld1;
+
+ private DataTable _dataTable;
+
+ static SimpleUnaryOpTest__SqrtScalar_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleUnaryOpTest__SqrtScalar_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, new Single[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.SqrtScalar(
+ Unsafe.Read<Vector64<Single>>(_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.SqrtScalar(
+ AdvSimd.LoadVector64((Single*)(_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.SqrtScalar), new Type[] { typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load));
+
+ var result = typeof(AdvSimd).GetMethod(nameof(AdvSimd.SqrtScalar), new Type[] { typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.SqrtScalar(
+ _clsVar1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ {
+ var result = AdvSimd.SqrtScalar(
+ AdvSimd.LoadVector64((Single*)(pClsVar1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var op1 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr);
+ var result = AdvSimd.SqrtScalar(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+ var op1 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr));
+ var result = AdvSimd.SqrtScalar(op1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleUnaryOpTest__SqrtScalar_Vector64_Single();
+ var result = AdvSimd.SqrtScalar(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__SqrtScalar_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ {
+ var result = AdvSimd.SqrtScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.SqrtScalar(_fld1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ {
+ var result = AdvSimd.SqrtScalar(
+ AdvSimd.LoadVector64((Single*)(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.SqrtScalar(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.SqrtScalar(
+ AdvSimd.LoadVector64((Single*)(&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(Vector64<Single> op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, outArray, method);
+ }
+
+ private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[0])) != BitConverter.SingleToInt32Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SqrtScalar)}<Single>(Vector64<Single>): {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 Subtract_Vector128_Byte()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_Byte();
+
+ 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__Subtract_Vector128_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector128<Byte> _fld1;
+ public Vector128<Byte> _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<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Subtract_Vector128_Byte testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector128_Byte testClass)
+ {
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector128<Byte> _clsVar1;
+ private static Vector128<Byte> _clsVar2;
+
+ private Vector128<Byte> _fld1;
+ private Vector128<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_Vector128_Byte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__Subtract_Vector128_Byte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.Subtract(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.Subtract(
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.Subtract), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.Subtract), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.Subtract(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Byte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector128((Byte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_Byte();
+ var result = AdvSimd.Subtract(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__Subtract_Vector128_Byte();
+
+ fixed (Vector128<Byte>* pFld1 = &test._fld1)
+ fixed (Vector128<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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.Subtract(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.Subtract(
+ AdvSimd.LoadVector128((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector128((Byte*)(&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(Vector128<Byte> op1, Vector128<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, 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];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ 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, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<Byte>(Vector128<Byte>, Vector128<Byte>): {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 Subtract_Vector128_Int16()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_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__Subtract_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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 Vector128<Int16> _fld1;
+ public Vector128<Int16> _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<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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__Subtract_Vector128_Int16 testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector128_Int16 testClass)
+ {
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector128<Int16> _clsVar1;
+ private static Vector128<Int16> _clsVar2;
+
+ private Vector128<Int16> _fld1;
+ private Vector128<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_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>>());
+ 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__Subtract_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 < 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.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Subtract(
+ Unsafe.Read<Vector128<Int16>>(_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.Subtract(
+ AdvSimd.LoadVector128((Int16*)(_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.Subtract), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int16>>(_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.Subtract), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int16*)(_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.Subtract(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector128((Int16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_Int16();
+ var result = AdvSimd.Subtract(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__Subtract_Vector128_Int16();
+
+ fixed (Vector128<Int16>* pFld1 = &test._fld1)
+ fixed (Vector128<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Int16*)(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.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Int16*)(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.Subtract(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.Subtract(
+ AdvSimd.LoadVector128((Int16*)(&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(Vector128<Int16> op1, Vector128<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, 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];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<Int16>(Vector128<Int16>, 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 Subtract_Vector128_Int32()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_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__Subtract_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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 Vector128<Int32> _fld1;
+ public Vector128<Int32> _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<Vector128<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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__Subtract_Vector128_Int32 testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector128_Int32 testClass)
+ {
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector128<Int32> _clsVar1;
+ private static Vector128<Int32> _clsVar2;
+
+ private Vector128<Int32> _fld1;
+ private Vector128<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_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>>());
+ 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__Subtract_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 < 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.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Subtract(
+ Unsafe.Read<Vector128<Int32>>(_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.Subtract(
+ AdvSimd.LoadVector128((Int32*)(_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.Subtract), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int32>>(_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.Subtract), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int32*)(_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.Subtract(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector128((Int32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_Int32();
+ var result = AdvSimd.Subtract(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__Subtract_Vector128_Int32();
+
+ fixed (Vector128<Int32>* pFld1 = &test._fld1)
+ fixed (Vector128<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Int32*)(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.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Int32*)(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.Subtract(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.Subtract(
+ AdvSimd.LoadVector128((Int32*)(&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(Vector128<Int32> op1, Vector128<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, 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];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<Int32>(Vector128<Int32>, 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 Subtract_Vector128_Int64()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_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__Subtract_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(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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<Int64, 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 Vector128<Int64> _fld1;
+ public Vector128<Int64> _fld2;
+
+ 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>>());
+ 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__Subtract_Vector128_Int64 testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector128_Int64 testClass)
+ {
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Int64*)(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<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+ private static Int64[] _data2 = new Int64[Op2ElementCount];
+
+ private static Vector128<Int64> _clsVar1;
+ private static Vector128<Int64> _clsVar2;
+
+ private Vector128<Int64> _fld1;
+ private Vector128<Int64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_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>>());
+ 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__Subtract_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 < 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.GetInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new Int64[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.Subtract(
+ Unsafe.Read<Vector128<Int64>>(_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.Subtract(
+ AdvSimd.LoadVector128((Int64*)(_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.Subtract), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(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.Subtract), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Subtract(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int64>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Int64*)(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<Vector128<Int64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector128((Int64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_Int64();
+ var result = AdvSimd.Subtract(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__Subtract_Vector128_Int64();
+
+ fixed (Vector128<Int64>* pFld1 = &test._fld1)
+ fixed (Vector128<Int64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Int64*)(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.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Int64*)(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.Subtract(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.Subtract(
+ AdvSimd.LoadVector128((Int64*)(&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(Vector128<Int64> op1, Vector128<Int64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[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<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<Int64>(Vector128<Int64>, 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 Subtract_Vector128_SByte()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_SByte();
+
+ 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__Subtract_Vector128_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector128<SByte> _fld1;
+ public Vector128<SByte> _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<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Subtract_Vector128_SByte testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector128_SByte testClass)
+ {
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector128<SByte> _clsVar1;
+ private static Vector128<SByte> _clsVar2;
+
+ private Vector128<SByte> _fld1;
+ private Vector128<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_Vector128_SByte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__Subtract_Vector128_SByte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Subtract(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.Subtract(
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.Subtract), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.Subtract), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.Subtract(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_SByte();
+ var result = AdvSimd.Subtract(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__Subtract_Vector128_SByte();
+
+ fixed (Vector128<SByte>* pFld1 = &test._fld1)
+ fixed (Vector128<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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.Subtract(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.Subtract(
+ AdvSimd.LoadVector128((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector128((SByte*)(&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(Vector128<SByte> op1, Vector128<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, 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];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ 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, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<SByte>(Vector128<SByte>, Vector128<SByte>): {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 Subtract_Vector128_Single()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_Single();
+
+ 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__Subtract_Vector128_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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 Vector128<Single> _fld1;
+ public Vector128<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Subtract_Vector128_Single testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector128_Single testClass)
+ {
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_Vector128_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Subtract_Vector128_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.Subtract(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_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.Subtract(
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_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.Subtract), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(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.Subtract), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Subtract(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Single*)(pClsVar1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_Single();
+ var result = AdvSimd.Subtract(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__Subtract_Vector128_Single();
+
+ fixed (Vector128<Single>* pFld1 = &test._fld1)
+ fixed (Vector128<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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.Subtract(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.Subtract(
+ AdvSimd.LoadVector128((Single*)(&test._fld1)),
+ AdvSimd.LoadVector128((Single*)(&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(Vector128<Single> op1, Vector128<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Subtract(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<Single>(Vector128<Single>, Vector128<Single>): {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 Subtract_Vector128_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_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__Subtract_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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 Vector128<UInt16> _fld1;
+ public Vector128<UInt16> _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<Vector128<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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__Subtract_Vector128_UInt16 testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector128_UInt16 testClass)
+ {
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector128<UInt16> _clsVar1;
+ private static Vector128<UInt16> _clsVar2;
+
+ private Vector128<UInt16> _fld1;
+ private Vector128<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_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>>());
+ 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__Subtract_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 < 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.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.Subtract(
+ Unsafe.Read<Vector128<UInt16>>(_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.Subtract(
+ AdvSimd.LoadVector128((UInt16*)(_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.Subtract), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt16>>(_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.Subtract), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt16*)(_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.Subtract(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector128((UInt16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_UInt16();
+ var result = AdvSimd.Subtract(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__Subtract_Vector128_UInt16();
+
+ fixed (Vector128<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((UInt16*)(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.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((UInt16*)(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.Subtract(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.Subtract(
+ AdvSimd.LoadVector128((UInt16*)(&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(Vector128<UInt16> op1, Vector128<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, 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];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<UInt16>(Vector128<UInt16>, 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 Subtract_Vector128_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_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__Subtract_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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 Vector128<UInt32> _fld1;
+ public Vector128<UInt32> _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<Vector128<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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__Subtract_Vector128_UInt32 testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector128_UInt32 testClass)
+ {
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector128<UInt32> _clsVar1;
+ private static Vector128<UInt32> _clsVar2;
+
+ private Vector128<UInt32> _fld1;
+ private Vector128<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_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>>());
+ 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__Subtract_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 < 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.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.Subtract(
+ Unsafe.Read<Vector128<UInt32>>(_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.Subtract(
+ AdvSimd.LoadVector128((UInt32*)(_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.Subtract), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt32>>(_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.Subtract), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt32*)(_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.Subtract(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector128((UInt32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_UInt32();
+ var result = AdvSimd.Subtract(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__Subtract_Vector128_UInt32();
+
+ fixed (Vector128<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((UInt32*)(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.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((UInt32*)(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.Subtract(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.Subtract(
+ AdvSimd.LoadVector128((UInt32*)(&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(Vector128<UInt32> op1, Vector128<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, 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];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<UInt32>(Vector128<UInt32>, 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 Subtract_Vector128_UInt64()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_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__Subtract_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(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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<UInt64, 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 Vector128<UInt64> _fld1;
+ public Vector128<UInt64> _fld2;
+
+ 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>>());
+ 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__Subtract_Vector128_UInt64 testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector128_UInt64 testClass)
+ {
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((UInt64*)(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<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+ private static UInt64[] _data2 = new UInt64[Op2ElementCount];
+
+ private static Vector128<UInt64> _clsVar1;
+ private static Vector128<UInt64> _clsVar2;
+
+ private Vector128<UInt64> _fld1;
+ private Vector128<UInt64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_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>>());
+ 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__Subtract_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 < 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.GetUInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt64[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.Subtract(
+ Unsafe.Read<Vector128<UInt64>>(_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.Subtract(
+ AdvSimd.LoadVector128((UInt64*)(_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.Subtract), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(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.Subtract), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Subtract(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt64>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((UInt64*)(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<Vector128<UInt64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector128((UInt64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector128_UInt64();
+ var result = AdvSimd.Subtract(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__Subtract_Vector128_UInt64();
+
+ fixed (Vector128<UInt64>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((UInt64*)(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.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector128((UInt64*)(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.Subtract(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.Subtract(
+ AdvSimd.LoadVector128((UInt64*)(&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(Vector128<UInt64> op1, Vector128<UInt64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[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<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<UInt64>(Vector128<UInt64>, 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 Subtract_Vector64_Byte()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_Byte();
+
+ 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__Subtract_Vector64_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector64<Byte> _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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Subtract_Vector64_Byte testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector64_Byte testClass)
+ {
+ fixed (Vector64<Byte>* pFld1 = &_fld1)
+ fixed (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector64<Byte> _clsVar1;
+ private static Vector64<Byte> _clsVar2;
+
+ private Vector64<Byte> _fld1;
+ private Vector64<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__Subtract_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.Subtract(
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_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.Subtract(
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_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.Subtract), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Subtract), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Subtract(
+ _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 (Vector64<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector64((Byte*)(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<Vector64<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector64((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_Byte();
+ var result = AdvSimd.Subtract(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__Subtract_Vector64_Byte();
+
+ fixed (Vector64<Byte>* pFld1 = &test._fld1)
+ fixed (Vector64<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Subtract(_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 (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(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.Subtract(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.Subtract(
+ AdvSimd.LoadVector64((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector64((Byte*)(&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, Vector64<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[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<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<Byte>(Vector64<Byte>, Vector64<Byte>): {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 Subtract_Vector64_Int16()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_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__Subtract_Vector64_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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<Int16> _fld1;
+ public Vector64<Int16> _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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Subtract_Vector64_Int16 testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector64_Int16 testClass)
+ {
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ fixed (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((Int16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector64<Int16> _clsVar1;
+ private static Vector64<Int16> _clsVar2;
+
+ private Vector64<Int16> _fld1;
+ private Vector64<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ }
+
+ public SimpleBinaryOpTest__Subtract_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Subtract(
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Subtract(
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Subtract), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Subtract), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Subtract(
+ _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 (Vector64<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Int16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector64((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_Int16();
+ var result = AdvSimd.Subtract(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__Subtract_Vector64_Int16();
+
+ fixed (Vector64<Int16>* pFld1 = &test._fld1)
+ fixed (Vector64<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Subtract(_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 (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Subtract(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.Subtract(
+ AdvSimd.LoadVector64((Int16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int16> op1, Vector64<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<Int16>(Vector64<Int16>, Vector64<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 Subtract_Vector64_Int32()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_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__Subtract_Vector64_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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<Int32> _fld1;
+ public Vector64<Int32> _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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref testStruct._fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Subtract_Vector64_Int32 testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector64_Int32 testClass)
+ {
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ fixed (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((Int32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector64<Int32> _clsVar1;
+ private static Vector64<Int32> _clsVar2;
+
+ private Vector64<Int32> _fld1;
+ private Vector64<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ }
+
+ public SimpleBinaryOpTest__Subtract_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Subtract(
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Subtract(
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Subtract), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Subtract), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Subtract(
+ _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 (Vector64<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Int32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector64((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_Int32();
+ var result = AdvSimd.Subtract(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__Subtract_Vector64_Int32();
+
+ fixed (Vector64<Int32>* pFld1 = &test._fld1)
+ fixed (Vector64<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Subtract(_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 (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Subtract(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.Subtract(
+ AdvSimd.LoadVector64((Int32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int32> op1, Vector64<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<Int32>(Vector64<Int32>, Vector64<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 Subtract_Vector64_SByte()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_SByte();
+
+ 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__Subtract_Vector64_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector64<SByte> _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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Subtract_Vector64_SByte testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector64_SByte testClass)
+ {
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ fixed (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector64<SByte> _clsVar1;
+ private static Vector64<SByte> _clsVar2;
+
+ private Vector64<SByte> _fld1;
+ private Vector64<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__Subtract_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Subtract(
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_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.Subtract(
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_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.Subtract), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Subtract), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Subtract(
+ _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 (Vector64<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector64((SByte*)(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<Vector64<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector64((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_SByte();
+ var result = AdvSimd.Subtract(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__Subtract_Vector64_SByte();
+
+ fixed (Vector64<SByte>* pFld1 = &test._fld1)
+ fixed (Vector64<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Subtract(_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 (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(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.Subtract(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.Subtract(
+ AdvSimd.LoadVector64((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector64((SByte*)(&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, Vector64<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[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<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<SByte>(Vector64<SByte>, Vector64<SByte>): {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 Subtract_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_Single();
+
+ 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__Subtract_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Subtract_Vector64_Single testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Subtract_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.Subtract(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.Subtract(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.Subtract), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(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.Subtract), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Subtract(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_Single();
+ var result = AdvSimd.Subtract(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__Subtract_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.Subtract(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.Subtract(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Subtract(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<Single>(Vector64<Single>, Vector64<Single>): {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 Subtract_Vector64_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_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__Subtract_Vector64_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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<UInt16> _fld1;
+ public Vector64<UInt16> _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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Subtract_Vector64_UInt16 testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector64_UInt16 testClass)
+ {
+ fixed (Vector64<UInt16>* pFld1 = &_fld1)
+ fixed (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((UInt16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector64<UInt16> _clsVar1;
+ private static Vector64<UInt16> _clsVar2;
+
+ private Vector64<UInt16> _fld1;
+ private Vector64<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _clsVar2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ }
+
+ public SimpleBinaryOpTest__Subtract_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.Subtract(
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Subtract(
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Subtract), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Subtract), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Subtract(
+ _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 (Vector64<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((UInt16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector64((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_UInt16();
+ var result = AdvSimd.Subtract(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__Subtract_Vector64_UInt16();
+
+ fixed (Vector64<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Subtract(_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 (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Subtract(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.Subtract(
+ AdvSimd.LoadVector64((UInt16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt16> op1, Vector64<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] left, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<UInt16>(Vector64<UInt16>, Vector64<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 Subtract_Vector64_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_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__Subtract_Vector64_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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<UInt32> _fld1;
+ public Vector64<UInt32> _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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Subtract_Vector64_UInt32 testClass)
+ {
+ var result = AdvSimd.Subtract(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Subtract_Vector64_UInt32 testClass)
+ {
+ fixed (Vector64<UInt32>* pFld1 = &_fld1)
+ fixed (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((UInt32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector64<UInt32> _clsVar1;
+ private static Vector64<UInt32> _clsVar2;
+
+ private Vector64<UInt32> _fld1;
+ private Vector64<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Subtract_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _clsVar2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ }
+
+ public SimpleBinaryOpTest__Subtract_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.Subtract(
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Subtract(
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Subtract), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Subtract), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Subtract(
+ _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 (Vector64<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((UInt32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Subtract(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.LoadVector64((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Subtract(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Subtract_Vector64_UInt32();
+ var result = AdvSimd.Subtract(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__Subtract_Vector64_UInt32();
+
+ fixed (Vector64<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Subtract(_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 (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Subtract(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Subtract(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.Subtract(
+ AdvSimd.LoadVector64((UInt32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt32> op1, Vector64<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] left, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Subtract(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Subtract)}<UInt32>(Vector64<UInt32>, Vector64<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 SubtractScalar_Vector64_Double()
+ {
+ var test = new SimpleBinaryOpTest__SubtractScalar_Vector64_Double();
+
+ 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__SubtractScalar_Vector64_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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<Double> _fld1;
+ public Vector64<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__SubtractScalar_Vector64_Double testClass)
+ {
+ var result = AdvSimd.SubtractScalar(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractScalar_Vector64_Double testClass)
+ {
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector64<Double> _clsVar1;
+ private static Vector64<Double> _clsVar2;
+
+ private Vector64<Double> _fld1;
+ private Vector64<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__SubtractScalar_Vector64_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ }
+
+ public SimpleBinaryOpTest__SubtractScalar_Vector64_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[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.SubtractScalar(
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_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.SubtractScalar(
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_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.SubtractScalar), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(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.SubtractScalar), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.SubtractScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((Double*)(pClsVar1)),
+ AdvSimd.LoadVector64((Double*)(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<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.SubtractScalar(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((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.SubtractScalar(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__SubtractScalar_Vector64_Double();
+ var result = AdvSimd.SubtractScalar(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__SubtractScalar_Vector64_Double();
+
+ fixed (Vector64<Double>* pFld1 = &test._fld1)
+ fixed (Vector64<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.SubtractScalar(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(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.SubtractScalar(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.SubtractScalar(
+ AdvSimd.LoadVector64((Double*)(&test._fld1)),
+ AdvSimd.LoadVector64((Double*)(&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<Double> op1, Vector64<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.DoubleToInt64Bits(Helpers.Subtract(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractScalar)}<Double>(Vector64<Double>, Vector64<Double>): {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 SubtractScalar_Vector64_Int64()
+ {
+ var test = new SimpleBinaryOpTest__SubtractScalar_Vector64_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__SubtractScalar_Vector64_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(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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<Int64, 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<Int64> _fld1;
+ public Vector64<Int64> _fld2;
+
+ 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<Vector64<Int64>, byte>(ref testStruct._fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref testStruct._fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__SubtractScalar_Vector64_Int64 testClass)
+ {
+ var result = AdvSimd.SubtractScalar(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractScalar_Vector64_Int64 testClass)
+ {
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ fixed (Vector64<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((Int64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+ private static Int64[] _data2 = new Int64[Op2ElementCount];
+
+ private static Vector64<Int64> _clsVar1;
+ private static Vector64<Int64> _clsVar2;
+
+ private Vector64<Int64> _fld1;
+ private Vector64<Int64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__SubtractScalar_Vector64_Int64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ }
+
+ public SimpleBinaryOpTest__SubtractScalar_Vector64_Int64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new Int64[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.SubtractScalar(
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.SubtractScalar(
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.SubtractScalar), new Type[] { typeof(Vector64<Int64>), typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(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.SubtractScalar), new Type[] { typeof(Vector64<Int64>), typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.SubtractScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int64>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Int64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((Int64*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.SubtractScalar(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((Int64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.SubtractScalar(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__SubtractScalar_Vector64_Int64();
+ var result = AdvSimd.SubtractScalar(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__SubtractScalar_Vector64_Int64();
+
+ fixed (Vector64<Int64>* pFld1 = &test._fld1)
+ fixed (Vector64<Int64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((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.SubtractScalar(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ fixed (Vector64<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((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.SubtractScalar(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.SubtractScalar(
+ AdvSimd.LoadVector64((Int64*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int64> op1, Vector64<Int64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (Helpers.Subtract(left[0], right[0]) != result[0])
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (result[i] != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractScalar)}<Int64>(Vector64<Int64>, Vector64<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 SubtractScalar_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__SubtractScalar_Vector64_Single();
+
+ 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__SubtractScalar_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__SubtractScalar_Vector64_Single testClass)
+ {
+ var result = AdvSimd.SubtractScalar(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractScalar_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__SubtractScalar_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__SubtractScalar_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.SubtractScalar(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.SubtractScalar(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.SubtractScalar), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(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.SubtractScalar), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.SubtractScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.SubtractScalar(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.SubtractScalar(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__SubtractScalar_Vector64_Single();
+ var result = AdvSimd.SubtractScalar(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__SubtractScalar_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.SubtractScalar(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.SubtractScalar(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.SubtractScalar(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (BitConverter.SingleToInt32Bits(Helpers.Subtract(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0]))
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(result[i]) != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractScalar)}<Single>(Vector64<Single>, Vector64<Single>): {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 SubtractScalar_Vector64_UInt64()
+ {
+ var test = new SimpleBinaryOpTest__SubtractScalar_Vector64_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__SubtractScalar_Vector64_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(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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<UInt64, 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<UInt64> _fld1;
+ public Vector64<UInt64> _fld2;
+
+ 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<Vector64<UInt64>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__SubtractScalar_Vector64_UInt64 testClass)
+ {
+ var result = AdvSimd.SubtractScalar(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__SubtractScalar_Vector64_UInt64 testClass)
+ {
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ fixed (Vector64<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((UInt64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+ private static UInt64[] _data2 = new UInt64[Op2ElementCount];
+
+ private static Vector64<UInt64> _clsVar1;
+ private static Vector64<UInt64> _clsVar2;
+
+ private Vector64<UInt64> _fld1;
+ private Vector64<UInt64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__SubtractScalar_Vector64_UInt64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _clsVar1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _clsVar2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ }
+
+ public SimpleBinaryOpTest__SubtractScalar_Vector64_UInt64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt64[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.SubtractScalar(
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.SubtractScalar(
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.SubtractScalar), new Type[] { typeof(Vector64<UInt64>), typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(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.SubtractScalar), new Type[] { typeof(Vector64<UInt64>), typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.SubtractScalar(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<UInt64>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<UInt64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((UInt64*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.SubtractScalar(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((UInt64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.SubtractScalar(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__SubtractScalar_Vector64_UInt64();
+ var result = AdvSimd.SubtractScalar(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__SubtractScalar_Vector64_UInt64();
+
+ fixed (Vector64<UInt64>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((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.SubtractScalar(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ fixed (Vector64<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.SubtractScalar(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((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.SubtractScalar(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.SubtractScalar(
+ AdvSimd.LoadVector64((UInt64*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt64> op1, Vector64<UInt64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ if (Helpers.Subtract(left[0], right[0]) != result[0])
+ {
+ succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < RetElementCount; i++)
+ {
+ if (result[i] != 0)
+ {
+ succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.SubtractScalar)}<UInt64>(Vector64<UInt64>, Vector64<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 Xor_Vector128_Byte()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector128_Byte();
+
+ 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__Xor_Vector128_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector128<Byte> _fld1;
+ public Vector128<Byte> _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<Vector128<Byte>, byte>(ref testStruct._fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector128_Byte testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector128_Byte testClass)
+ {
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector128<Byte> _clsVar1;
+ private static Vector128<Byte> _clsVar2;
+
+ private Vector128<Byte> _fld1;
+ private Vector128<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector128_Byte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector128_Byte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.Xor(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.Xor(
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.Xor), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_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.Xor), new Type[] { typeof(Vector128<Byte>), typeof(Vector128<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Byte*)(_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.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Byte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector128((Byte*)(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<Vector128<Byte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector128((Byte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector128_Byte();
+ var result = AdvSimd.Xor(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__Xor_Vector128_Byte();
+
+ fixed (Vector128<Byte>* pFld1 = &test._fld1)
+ fixed (Vector128<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Byte>* pFld1 = &_fld1)
+ fixed (Vector128<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Byte*)(pFld1)),
+ AdvSimd.LoadVector128((Byte*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector128((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector128((Byte*)(&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(Vector128<Byte> op1, Vector128<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, 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];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Byte>>());
+ 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, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<Byte>(Vector128<Byte>, Vector128<Byte>): {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 Xor_Vector128_Double()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector128_Double();
+
+ 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__Xor_Vector128_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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 Vector128<Double> _fld1;
+ public Vector128<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector128_Double testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector128_Double testClass)
+ {
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+ private static Vector128<Double> _clsVar2;
+
+ private Vector128<Double> _fld1;
+ private Vector128<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector128_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector128_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[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.Xor(
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_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.Xor(
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_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.Xor), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(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.Xor), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Double*)(pClsVar1)),
+ AdvSimd.LoadVector128((Double*)(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<Vector128<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector128_Double();
+ var result = AdvSimd.Xor(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__Xor_Vector128_Double();
+
+ fixed (Vector128<Double>* pFld1 = &test._fld1)
+ fixed (Vector128<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Double>* pFld1 = &_fld1)
+ fixed (Vector128<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Double*)(pFld1)),
+ AdvSimd.LoadVector128((Double*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector128((Double*)(&test._fld1)),
+ AdvSimd.LoadVector128((Double*)(&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(Vector128<Double> op1, Vector128<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.Xor(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<Double>(Vector128<Double>, Vector128<Double>): {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 Xor_Vector128_Int16()
+ {
+ var test = new SimpleBinaryOpTest__Xor_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__Xor_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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 Vector128<Int16> _fld1;
+ public Vector128<Int16> _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<Vector128<Int16>, byte>(ref testStruct._fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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__Xor_Vector128_Int16 testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector128_Int16 testClass)
+ {
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector128<Int16> _clsVar1;
+ private static Vector128<Int16> _clsVar2;
+
+ private Vector128<Int16> _fld1;
+ private Vector128<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_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>>());
+ 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__Xor_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 < 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.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Xor(
+ Unsafe.Read<Vector128<Int16>>(_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.Xor(
+ AdvSimd.LoadVector128((Int16*)(_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.Xor), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int16>>(_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.Xor), new Type[] { typeof(Vector128<Int16>), typeof(Vector128<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int16*)(_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.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Int16*)(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<Vector128<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector128((Int16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector128_Int16();
+ var result = AdvSimd.Xor(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__Xor_Vector128_Int16();
+
+ fixed (Vector128<Int16>* pFld1 = &test._fld1)
+ fixed (Vector128<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Int16*)(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.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int16>* pFld1 = &_fld1)
+ fixed (Vector128<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Int16*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector128((Int16*)(&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(Vector128<Int16> op1, Vector128<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, 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];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int16>>());
+ 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, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<Int16>(Vector128<Int16>, 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 Xor_Vector128_Int32()
+ {
+ var test = new SimpleBinaryOpTest__Xor_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__Xor_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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 Vector128<Int32> _fld1;
+ public Vector128<Int32> _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<Vector128<Int32>, byte>(ref testStruct._fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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__Xor_Vector128_Int32 testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector128_Int32 testClass)
+ {
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector128<Int32> _clsVar1;
+ private static Vector128<Int32> _clsVar2;
+
+ private Vector128<Int32> _fld1;
+ private Vector128<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_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>>());
+ 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__Xor_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 < 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.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Xor(
+ Unsafe.Read<Vector128<Int32>>(_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.Xor(
+ AdvSimd.LoadVector128((Int32*)(_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.Xor), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int32>>(_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.Xor), new Type[] { typeof(Vector128<Int32>), typeof(Vector128<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int32*)(_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.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Int32*)(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<Vector128<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector128((Int32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector128_Int32();
+ var result = AdvSimd.Xor(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__Xor_Vector128_Int32();
+
+ fixed (Vector128<Int32>* pFld1 = &test._fld1)
+ fixed (Vector128<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Int32*)(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.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int32>* pFld1 = &_fld1)
+ fixed (Vector128<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Int32*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector128((Int32*)(&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(Vector128<Int32> op1, Vector128<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, 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];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int32>>());
+ 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, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<Int32>(Vector128<Int32>, 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 Xor_Vector128_Int64()
+ {
+ var test = new SimpleBinaryOpTest__Xor_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__Xor_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(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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<Int64, 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 Vector128<Int64> _fld1;
+ public Vector128<Int64> _fld2;
+
+ 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>>());
+ 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__Xor_Vector128_Int64 testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector128_Int64 testClass)
+ {
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Int64*)(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<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+ private static Int64[] _data2 = new Int64[Op2ElementCount];
+
+ private static Vector128<Int64> _clsVar1;
+ private static Vector128<Int64> _clsVar2;
+
+ private Vector128<Int64> _fld1;
+ private Vector128<Int64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_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>>());
+ 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__Xor_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 < 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.GetInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new Int64[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.Xor(
+ Unsafe.Read<Vector128<Int64>>(_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.Xor(
+ AdvSimd.LoadVector128((Int64*)(_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.Xor), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(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.Xor), new Type[] { typeof(Vector128<Int64>), typeof(Vector128<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Int64>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Int64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Int64*)(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<Vector128<Int64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector128((Int64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Int64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector128_Int64();
+ var result = AdvSimd.Xor(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__Xor_Vector128_Int64();
+
+ fixed (Vector128<Int64>* pFld1 = &test._fld1)
+ fixed (Vector128<Int64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Int64*)(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.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Int64>* pFld1 = &_fld1)
+ fixed (Vector128<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Int64*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector128((Int64*)(&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(Vector128<Int64> op1, Vector128<Int64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[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<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<Int64>(Vector128<Int64>, 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 Xor_Vector128_SByte()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector128_SByte();
+
+ 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__Xor_Vector128_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector128<SByte> _fld1;
+ public Vector128<SByte> _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<Vector128<SByte>, byte>(ref testStruct._fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector128_SByte testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector128_SByte testClass)
+ {
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector128<SByte> _clsVar1;
+ private static Vector128<SByte> _clsVar2;
+
+ private Vector128<SByte> _fld1;
+ private Vector128<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector128_SByte()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector128_SByte()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Xor(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.Xor(
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.Xor), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_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.Xor), new Type[] { typeof(Vector128<SByte>), typeof(Vector128<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((SByte*)(_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.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<SByte>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector128((SByte*)(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<Vector128<SByte>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector128((SByte*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector128_SByte();
+ var result = AdvSimd.Xor(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__Xor_Vector128_SByte();
+
+ fixed (Vector128<SByte>* pFld1 = &test._fld1)
+ fixed (Vector128<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<SByte>* pFld1 = &_fld1)
+ fixed (Vector128<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((SByte*)(pFld1)),
+ AdvSimd.LoadVector128((SByte*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector128((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector128((SByte*)(&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(Vector128<SByte> op1, Vector128<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, 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];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<SByte>>());
+ 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, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<SByte>(Vector128<SByte>, Vector128<SByte>): {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 Xor_Vector128_Single()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector128_Single();
+
+ 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__Xor_Vector128_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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 Vector128<Single> _fld1;
+ public Vector128<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector128_Single testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector128_Single testClass)
+ {
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector128<Single> _clsVar1;
+ private static Vector128<Single> _clsVar2;
+
+ private Vector128<Single> _fld1;
+ private Vector128<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector128_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector128_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.Xor(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_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.Xor(
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_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.Xor), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(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.Xor), new Type[] { typeof(Vector128<Single>), typeof(Vector128<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Single*)(pClsVar1)),
+ AdvSimd.LoadVector128((Single*)(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<Vector128<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector128_Single();
+ var result = AdvSimd.Xor(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__Xor_Vector128_Single();
+
+ fixed (Vector128<Single>* pFld1 = &test._fld1)
+ fixed (Vector128<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<Single>* pFld1 = &_fld1)
+ fixed (Vector128<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((Single*)(pFld1)),
+ AdvSimd.LoadVector128((Single*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector128((Single*)(&test._fld1)),
+ AdvSimd.LoadVector128((Single*)(&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(Vector128<Single> op1, Vector128<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Xor(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<Single>(Vector128<Single>, Vector128<Single>): {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 Xor_Vector128_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__Xor_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__Xor_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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 Vector128<UInt16> _fld1;
+ public Vector128<UInt16> _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<Vector128<UInt16>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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__Xor_Vector128_UInt16 testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector128_UInt16 testClass)
+ {
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector128<UInt16> _clsVar1;
+ private static Vector128<UInt16> _clsVar2;
+
+ private Vector128<UInt16> _fld1;
+ private Vector128<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_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>>());
+ 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__Xor_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 < 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.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.Xor(
+ Unsafe.Read<Vector128<UInt16>>(_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.Xor(
+ AdvSimd.LoadVector128((UInt16*)(_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.Xor), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt16>>(_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.Xor), new Type[] { typeof(Vector128<UInt16>), typeof(Vector128<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt16*)(_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.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt16>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((UInt16*)(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<Vector128<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector128((UInt16*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector128_UInt16();
+ var result = AdvSimd.Xor(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__Xor_Vector128_UInt16();
+
+ fixed (Vector128<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((UInt16*)(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.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt16>* pFld1 = &_fld1)
+ fixed (Vector128<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((UInt16*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector128((UInt16*)(&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(Vector128<UInt16> op1, Vector128<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, 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];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt16>>());
+ 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, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<UInt16>(Vector128<UInt16>, 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 Xor_Vector128_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__Xor_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__Xor_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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 Vector128<UInt32> _fld1;
+ public Vector128<UInt32> _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<Vector128<UInt32>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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__Xor_Vector128_UInt32 testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector128_UInt32 testClass)
+ {
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector128<UInt32> _clsVar1;
+ private static Vector128<UInt32> _clsVar2;
+
+ private Vector128<UInt32> _fld1;
+ private Vector128<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_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>>());
+ 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__Xor_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 < 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.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.Xor(
+ Unsafe.Read<Vector128<UInt32>>(_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.Xor(
+ AdvSimd.LoadVector128((UInt32*)(_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.Xor), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt32>>(_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.Xor), new Type[] { typeof(Vector128<UInt32>), typeof(Vector128<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt32*)(_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.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt32>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((UInt32*)(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<Vector128<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector128((UInt32*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector128_UInt32();
+ var result = AdvSimd.Xor(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__Xor_Vector128_UInt32();
+
+ fixed (Vector128<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((UInt32*)(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.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt32>* pFld1 = &_fld1)
+ fixed (Vector128<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((UInt32*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector128((UInt32*)(&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(Vector128<UInt32> op1, Vector128<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, 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];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt32>>());
+ 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, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<UInt32>(Vector128<UInt32>, 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 Xor_Vector128_UInt64()
+ {
+ var test = new SimpleBinaryOpTest__Xor_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__Xor_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(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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<UInt64, 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 Vector128<UInt64> _fld1;
+ public Vector128<UInt64> _fld2;
+
+ 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>>());
+ 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__Xor_Vector128_UInt64 testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector128_UInt64 testClass)
+ {
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((UInt64*)(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<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+ private static UInt64[] _data2 = new UInt64[Op2ElementCount];
+
+ private static Vector128<UInt64> _clsVar1;
+ private static Vector128<UInt64> _clsVar2;
+
+ private Vector128<UInt64> _fld1;
+ private Vector128<UInt64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_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>>());
+ 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__Xor_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 < 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.GetUInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt64[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.Xor(
+ Unsafe.Read<Vector128<UInt64>>(_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.Xor(
+ AdvSimd.LoadVector128((UInt64*)(_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.Xor), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(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.Xor), new Type[] { typeof(Vector128<UInt64>), typeof(Vector128<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector128<UInt64>* pClsVar1 = &_clsVar1)
+ fixed (Vector128<UInt64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((UInt64*)(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<Vector128<UInt64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector128((UInt64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector128((UInt64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector128_UInt64();
+ var result = AdvSimd.Xor(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__Xor_Vector128_UInt64();
+
+ fixed (Vector128<UInt64>* pFld1 = &test._fld1)
+ fixed (Vector128<UInt64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((UInt64*)(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.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector128<UInt64>* pFld1 = &_fld1)
+ fixed (Vector128<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector128((UInt64*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector128((UInt64*)(&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(Vector128<UInt64> op1, Vector128<UInt64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[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<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<UInt64>(Vector128<UInt64>, 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 Xor_Vector64_Byte()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector64_Byte();
+
+ 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__Xor_Vector64_Byte
+ {
+ 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, Byte[] inArray2, Byte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Byte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Byte>();
+ 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<Byte, 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 Vector64<Byte> _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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref testStruct._fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector64_Byte testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector64_Byte testClass)
+ {
+ fixed (Vector64<Byte>* pFld1 = &_fld1)
+ fixed (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Byte>>() / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[Op1ElementCount];
+ private static Byte[] _data2 = new Byte[Op2ElementCount];
+
+ private static Vector64<Byte> _clsVar1;
+ private static Vector64<Byte> _clsVar2;
+
+ private Vector64<Byte> _fld1;
+ private Vector64<Byte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector64_Byte()
+ {
+ 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.GetByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetByte(); }
+ _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.Xor(
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_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.Xor(
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_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.Xor), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Byte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Xor), new Type[] { typeof(Vector64<Byte>), typeof(Vector64<Byte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Byte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Byte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _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 (Vector64<Byte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Byte*)(pClsVar1)),
+ AdvSimd.LoadVector64((Byte*)(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<Vector64<Byte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector64((Byte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector64_Byte();
+ var result = AdvSimd.Xor(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__Xor_Vector64_Byte();
+
+ fixed (Vector64<Byte>* pFld1 = &test._fld1)
+ fixed (Vector64<Byte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Xor(_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 (Vector64<Byte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Byte*)(pFld1)),
+ AdvSimd.LoadVector64((Byte*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector64((Byte*)(&test._fld1)),
+ AdvSimd.LoadVector64((Byte*)(&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, Vector64<Byte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[Op2ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Byte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[Op1ElementCount];
+ Byte[] inArray2 = new Byte[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<Byte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Byte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<Byte>(Vector64<Byte>, Vector64<Byte>): {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 Xor_Vector64_Double()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector64_Double();
+
+ 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__Xor_Vector64_Double
+ {
+ 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(Double[] inArray1, Double[] inArray2, Double[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Double>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Double>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Double>();
+ 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<Double, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Double, 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<Double> _fld1;
+ public Vector64<Double> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector64_Double testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector64_Double testClass)
+ {
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Double>>() / sizeof(Double);
+
+ private static Double[] _data1 = new Double[Op1ElementCount];
+ private static Double[] _data2 = new Double[Op2ElementCount];
+
+ private static Vector64<Double> _clsVar1;
+ private static Vector64<Double> _clsVar2;
+
+ private Vector64<Double> _fld1;
+ private Vector64<Double> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector64_Double()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector64_Double()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
+ _dataTable = new DataTable(_data1, _data2, new Double[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.Xor(
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_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.Xor(
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_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.Xor), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(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.Xor), new Type[] { typeof(Vector64<Double>), typeof(Vector64<Double>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Double>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Double>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Double>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Double*)(pClsVar1)),
+ AdvSimd.LoadVector64((Double*)(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<Double>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Double>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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((Double*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Double*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector64_Double();
+ var result = AdvSimd.Xor(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__Xor_Vector64_Double();
+
+ fixed (Vector64<Double>* pFld1 = &test._fld1)
+ fixed (Vector64<Double>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Double>* pFld1 = &_fld1)
+ fixed (Vector64<Double>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Double*)(pFld1)),
+ AdvSimd.LoadVector64((Double*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector64((Double*)(&test._fld1)),
+ AdvSimd.LoadVector64((Double*)(&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<Double> op1, Vector64<Double> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[Op1ElementCount];
+ Double[] inArray2 = new Double[Op2ElementCount];
+ Double[] outArray = new Double[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Double>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Double>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(Helpers.Xor(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<Double>(Vector64<Double>, Vector64<Double>): {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 Xor_Vector64_Int16()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector64_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__Xor_Vector64_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(Int16[] inArray1, Int16[] inArray2, Int16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int16>();
+ 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<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<Int16> _fld1;
+ public Vector64<Int16> _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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref testStruct._fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector64_Int16 testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector64_Int16 testClass)
+ {
+ fixed (Vector64<Int16>* pFld1 = &_fld1)
+ fixed (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((Int16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int16>>() / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[Op1ElementCount];
+ private static Int16[] _data2 = new Int16[Op2ElementCount];
+
+ private static Vector64<Int16> _clsVar1;
+ private static Vector64<Int16> _clsVar2;
+
+ private Vector64<Int16> _fld1;
+ private Vector64<Int16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector64_Int16()
+ {
+ 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.GetInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt16(); }
+ _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.Xor(
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Xor(
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Xor), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Xor), new Type[] { typeof(Vector64<Int16>), typeof(Vector64<Int16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _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 (Vector64<Int16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Int16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector64((Int16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector64_Int16();
+ var result = AdvSimd.Xor(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__Xor_Vector64_Int16();
+
+ fixed (Vector64<Int16>* pFld1 = &test._fld1)
+ fixed (Vector64<Int16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Xor(_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 (Vector64<Int16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Int16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Xor(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.Xor(
+ AdvSimd.LoadVector64((Int16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int16> op1, Vector64<Int16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[Op2ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[Op1ElementCount];
+ Int16[] inArray2 = new Int16[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<Int16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<Int16>(Vector64<Int16>, Vector64<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 Xor_Vector64_Int32()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector64_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__Xor_Vector64_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(Int32[] inArray1, Int32[] inArray2, Int32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int32>();
+ 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<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<Int32> _fld1;
+ public Vector64<Int32> _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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref testStruct._fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector64_Int32 testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector64_Int32 testClass)
+ {
+ fixed (Vector64<Int32>* pFld1 = &_fld1)
+ fixed (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((Int32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int32>>() / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[Op1ElementCount];
+ private static Int32[] _data2 = new Int32[Op2ElementCount];
+
+ private static Vector64<Int32> _clsVar1;
+ private static Vector64<Int32> _clsVar2;
+
+ private Vector64<Int32> _fld1;
+ private Vector64<Int32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector64_Int32()
+ {
+ 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.GetInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt32(); }
+ _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.Xor(
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Xor(
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Xor), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Xor), new Type[] { typeof(Vector64<Int32>), typeof(Vector64<Int32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _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 (Vector64<Int32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Int32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector64((Int32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector64_Int32();
+ var result = AdvSimd.Xor(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__Xor_Vector64_Int32();
+
+ fixed (Vector64<Int32>* pFld1 = &test._fld1)
+ fixed (Vector64<Int32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Xor(_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 (Vector64<Int32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Int32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Xor(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.Xor(
+ AdvSimd.LoadVector64((Int32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int32> op1, Vector64<Int32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[Op2ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[Op1ElementCount];
+ Int32[] inArray2 = new Int32[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<Int32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<Int32>(Vector64<Int32>, Vector64<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 Xor_Vector64_Int64()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector64_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__Xor_Vector64_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(Int64[] inArray1, Int64[] inArray2, Int64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Int64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Int64>();
+ 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<Int64, 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<Int64> _fld1;
+ public Vector64<Int64> _fld2;
+
+ 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<Vector64<Int64>, byte>(ref testStruct._fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref testStruct._fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector64_Int64 testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector64_Int64 testClass)
+ {
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ fixed (Vector64<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((Int64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Int64>>() / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[Op1ElementCount];
+ private static Int64[] _data2 = new Int64[Op2ElementCount];
+
+ private static Vector64<Int64> _clsVar1;
+ private static Vector64<Int64> _clsVar2;
+
+ private Vector64<Int64> _fld1;
+ private Vector64<Int64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector64_Int64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _clsVar2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector64_Int64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Int64>, byte>(ref _fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new Int64[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.Xor(
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Xor(
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Xor), new Type[] { typeof(Vector64<Int64>), typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Int64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(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.Xor), new Type[] { typeof(Vector64<Int64>), typeof(Vector64<Int64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Int64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Int64>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Int64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Int64*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<Int64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Int64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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((Int64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Int64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector64_Int64();
+ var result = AdvSimd.Xor(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__Xor_Vector64_Int64();
+
+ fixed (Vector64<Int64>* pFld1 = &test._fld1)
+ fixed (Vector64<Int64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((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.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Int64>* pFld1 = &_fld1)
+ fixed (Vector64<Int64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Int64*)(pFld1)),
+ AdvSimd.LoadVector64((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.Xor(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.Xor(
+ AdvSimd.LoadVector64((Int64*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<Int64> op1, Vector64<Int64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[Op1ElementCount];
+ Int64[] inArray2 = new Int64[Op2ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Int64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<Int64>(Vector64<Int64>, Vector64<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 Xor_Vector64_SByte()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector64_SByte();
+
+ 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__Xor_Vector64_SByte
+ {
+ 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, SByte[] inArray2, SByte[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<SByte>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<SByte>();
+ 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<SByte, 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 Vector64<SByte> _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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref testStruct._fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector64_SByte testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector64_SByte testClass)
+ {
+ fixed (Vector64<SByte>* pFld1 = &_fld1)
+ fixed (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<SByte>>() / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[Op1ElementCount];
+ private static SByte[] _data2 = new SByte[Op2ElementCount];
+
+ private static Vector64<SByte> _clsVar1;
+ private static Vector64<SByte> _clsVar2;
+
+ private Vector64<SByte> _fld1;
+ private Vector64<SByte> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector64_SByte()
+ {
+ 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.GetSByte(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSByte(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSByte(); }
+ _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.Xor(
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_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.Xor(
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_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.Xor), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<SByte>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Xor), new Type[] { typeof(Vector64<SByte>), typeof(Vector64<SByte>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((SByte*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<SByte>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _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 (Vector64<SByte>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((SByte*)(pClsVar1)),
+ AdvSimd.LoadVector64((SByte*)(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<Vector64<SByte>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector64((SByte*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector64_SByte();
+ var result = AdvSimd.Xor(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__Xor_Vector64_SByte();
+
+ fixed (Vector64<SByte>* pFld1 = &test._fld1)
+ fixed (Vector64<SByte>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Xor(_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 (Vector64<SByte>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((SByte*)(pFld1)),
+ AdvSimd.LoadVector64((SByte*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector64((SByte*)(&test._fld1)),
+ AdvSimd.LoadVector64((SByte*)(&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, Vector64<SByte> op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[Op2ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<SByte, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[Op1ElementCount];
+ SByte[] inArray2 = new SByte[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<SByte, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<SByte>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<SByte>(Vector64<SByte>, Vector64<SByte>): {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 Xor_Vector64_Single()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector64_Single();
+
+ 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__Xor_Vector64_Single
+ {
+ 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(Single[] inArray1, Single[] inArray2, Single[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<Single>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<Single>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<Single>();
+ 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<Single, byte>(ref inArray1[0]), (uint)sizeOfinArray1);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.AsRef<byte>(inArray2Ptr), ref Unsafe.As<Single, 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<Single> _fld1;
+ public Vector64<Single> _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector64_Single testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector64_Single testClass)
+ {
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<Single>>() / sizeof(Single);
+
+ private static Single[] _data1 = new Single[Op1ElementCount];
+ private static Single[] _data2 = new Single[Op2ElementCount];
+
+ private static Vector64<Single> _clsVar1;
+ private static Vector64<Single> _clsVar2;
+
+ private Vector64<Single> _fld1;
+ private Vector64<Single> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector64_Single()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector64_Single()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
+ _dataTable = new DataTable(_data1, _data2, new Single[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.Xor(
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_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.Xor(
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_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.Xor), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(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.Xor), new Type[] { typeof(Vector64<Single>), typeof(Vector64<Single>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<Single>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<Single>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<Single>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Single*)(pClsVar1)),
+ AdvSimd.LoadVector64((Single*)(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<Single>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<Single>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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((Single*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((Single*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector64_Single();
+ var result = AdvSimd.Xor(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__Xor_Vector64_Single();
+
+ fixed (Vector64<Single>* pFld1 = &test._fld1)
+ fixed (Vector64<Single>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(pFld2))
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
+ }
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<Single>* pFld1 = &_fld1)
+ fixed (Vector64<Single>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((Single*)(pFld1)),
+ AdvSimd.LoadVector64((Single*)(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.Xor(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.Xor(
+ AdvSimd.LoadVector64((Single*)(&test._fld1)),
+ AdvSimd.LoadVector64((Single*)(&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<Single> op1, Vector64<Single> op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray1 = new Single[Op1ElementCount];
+ Single[] inArray2 = new Single[Op2ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<Single>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<Single>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(Single[] left, Single[] right, Single[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (BitConverter.SingleToInt32Bits(Helpers.Xor(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i]))
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<Single>(Vector64<Single>, Vector64<Single>): {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 Xor_Vector64_UInt16()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector64_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__Xor_Vector64_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(UInt16[] inArray1, UInt16[] inArray2, UInt16[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt16>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt16>();
+ 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<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<UInt16> _fld1;
+ public Vector64<UInt16> _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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector64_UInt16 testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector64_UInt16 testClass)
+ {
+ fixed (Vector64<UInt16>* pFld1 = &_fld1)
+ fixed (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((UInt16*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt16>>() / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[Op1ElementCount];
+ private static UInt16[] _data2 = new UInt16[Op2ElementCount];
+
+ private static Vector64<UInt16> _clsVar1;
+ private static Vector64<UInt16> _clsVar2;
+
+ private Vector64<UInt16> _fld1;
+ private Vector64<UInt16> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _clsVar2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector64_UInt16()
+ {
+ 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.GetUInt16(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt16>, byte>(ref _fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt16(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt16(); }
+ _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.Xor(
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Xor(
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Xor), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Xor), new Type[] { typeof(Vector64<UInt16>), typeof(Vector64<UInt16>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt16*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt16>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _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 (Vector64<UInt16>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((UInt16*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt16>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt16>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector64((UInt16*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector64_UInt16();
+ var result = AdvSimd.Xor(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__Xor_Vector64_UInt16();
+
+ fixed (Vector64<UInt16>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt16>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Xor(_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 (Vector64<UInt16>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((UInt16*)(pFld1)),
+ AdvSimd.LoadVector64((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.Xor(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.Xor(
+ AdvSimd.LoadVector64((UInt16*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt16> op1, Vector64<UInt16> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[Op2ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[Op1ElementCount];
+ UInt16[] inArray2 = new UInt16[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<UInt16, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt16>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] left, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<UInt16>(Vector64<UInt16>, Vector64<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 Xor_Vector64_UInt32()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector64_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__Xor_Vector64_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(UInt32[] inArray1, UInt32[] inArray2, UInt32[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt32>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt32>();
+ 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<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<UInt32> _fld1;
+ public Vector64<UInt32> _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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector64_UInt32 testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector64_UInt32 testClass)
+ {
+ fixed (Vector64<UInt32>* pFld1 = &_fld1)
+ fixed (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((UInt32*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt32>>() / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[Op1ElementCount];
+ private static UInt32[] _data2 = new UInt32[Op2ElementCount];
+
+ private static Vector64<UInt32> _clsVar1;
+ private static Vector64<UInt32> _clsVar2;
+
+ private Vector64<UInt32> _fld1;
+ private Vector64<UInt32> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _clsVar2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector64_UInt32()
+ {
+ 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.GetUInt32(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt32>, byte>(ref _fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt32(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt32(); }
+ _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.Xor(
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Xor(
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Xor), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<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.Xor), new Type[] { typeof(Vector64<UInt32>), typeof(Vector64<UInt32>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt32*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt32>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _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 (Vector64<UInt32>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((UInt32*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt32>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt32>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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.LoadVector64((UInt32*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector64_UInt32();
+ var result = AdvSimd.Xor(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__Xor_Vector64_UInt32();
+
+ fixed (Vector64<UInt32>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt32>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Xor(_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 (Vector64<UInt32>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((UInt32*)(pFld1)),
+ AdvSimd.LoadVector64((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.Xor(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.Xor(
+ AdvSimd.LoadVector64((UInt32*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt32> op1, Vector64<UInt32> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[Op2ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[Op1ElementCount];
+ UInt32[] inArray2 = new UInt32[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<UInt32, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt32>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] left, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<UInt32>(Vector64<UInt32>, Vector64<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 Xor_Vector64_UInt64()
+ {
+ var test = new SimpleBinaryOpTest__Xor_Vector64_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__Xor_Vector64_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(UInt64[] inArray1, UInt64[] inArray2, UInt64[] outArray, int alignment)
+ {
+ int sizeOfinArray1 = inArray1.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfinArray2 = inArray2.Length * Unsafe.SizeOf<UInt64>();
+ int sizeOfoutArray = outArray.Length * Unsafe.SizeOf<UInt64>();
+ 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<UInt64, 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<UInt64> _fld1;
+ public Vector64<UInt64> _fld2;
+
+ 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<Vector64<UInt64>, byte>(ref testStruct._fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref testStruct._fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(SimpleBinaryOpTest__Xor_Vector64_UInt64 testClass)
+ {
+ var result = AdvSimd.Xor(_fld1, _fld2);
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+
+ public void RunStructFldScenario_Load(SimpleBinaryOpTest__Xor_Vector64_UInt64 testClass)
+ {
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ fixed (Vector64<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((UInt64*)(pFld2))
+ );
+
+ Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+ testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
+ }
+ }
+ }
+
+ private static readonly int LargestVectorSize = 8;
+
+ private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+ private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+ private static readonly int RetElementCount = Unsafe.SizeOf<Vector64<UInt64>>() / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[Op1ElementCount];
+ private static UInt64[] _data2 = new UInt64[Op2ElementCount];
+
+ private static Vector64<UInt64> _clsVar1;
+ private static Vector64<UInt64> _clsVar2;
+
+ private Vector64<UInt64> _fld1;
+ private Vector64<UInt64> _fld2;
+
+ private DataTable _dataTable;
+
+ static SimpleBinaryOpTest__Xor_Vector64_UInt64()
+ {
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _clsVar1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _clsVar2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ }
+
+ public SimpleBinaryOpTest__Xor_Vector64_UInt64()
+ {
+ Succeeded = true;
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector64<UInt64>, byte>(ref _fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetUInt64(); }
+ for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetUInt64(); }
+ _dataTable = new DataTable(_data1, _data2, new UInt64[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.Xor(
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<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.Xor(
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((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.Xor), new Type[] { typeof(Vector64<UInt64>), typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray2Ptr)
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(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.Xor), new Type[] { typeof(Vector64<UInt64>), typeof(Vector64<UInt64>) })
+ .Invoke(null, new object[] {
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray1Ptr)),
+ AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr))
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector64<UInt64>)(result));
+ ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = AdvSimd.Xor(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario_Load));
+
+ fixed (Vector64<UInt64>* pClsVar1 = &_clsVar1)
+ fixed (Vector64<UInt64>* pClsVar2 = &_clsVar2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((UInt64*)(pClsVar1)),
+ AdvSimd.LoadVector64((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<UInt64>>(_dataTable.inArray1Ptr);
+ var op2 = Unsafe.Read<Vector64<UInt64>>(_dataTable.inArray2Ptr);
+ var result = AdvSimd.Xor(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((UInt64*)(_dataTable.inArray1Ptr));
+ var op2 = AdvSimd.LoadVector64((UInt64*)(_dataTable.inArray2Ptr));
+ var result = AdvSimd.Xor(op1, op2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(op1, op2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new SimpleBinaryOpTest__Xor_Vector64_UInt64();
+ var result = AdvSimd.Xor(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__Xor_Vector64_UInt64();
+
+ fixed (Vector64<UInt64>* pFld1 = &test._fld1)
+ fixed (Vector64<UInt64>* pFld2 = &test._fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((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.Xor(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
+ }
+
+ public void RunClassFldScenario_Load()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario_Load));
+
+ fixed (Vector64<UInt64>* pFld1 = &_fld1)
+ fixed (Vector64<UInt64>* pFld2 = &_fld2)
+ {
+ var result = AdvSimd.Xor(
+ AdvSimd.LoadVector64((UInt64*)(pFld1)),
+ AdvSimd.LoadVector64((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.Xor(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.Xor(
+ AdvSimd.LoadVector64((UInt64*)(&test._fld1)),
+ AdvSimd.LoadVector64((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<UInt64> op1, Vector64<UInt64> op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), op1);
+ Unsafe.WriteUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), op2);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(void* op1, void* op2, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[Op1ElementCount];
+ UInt64[] inArray2 = new UInt64[Op2ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(op1), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(op2), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector64<UInt64>>());
+
+ ValidateResult(inArray1, inArray2, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ bool succeeded = true;
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if (Helpers.Xor(left[i], right[i]) != result[i])
+ {
+ succeeded = false;
+ break;
+ }
+ }
+
+ if (!succeeded)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(AdvSimd)}.{nameof(AdvSimd.Xor)}<UInt64>(Vector64<UInt64>, Vector64<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;
+ }
+ }
+ }
+}
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "AddScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.Add(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}),
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "AddScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddScalar", ["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.Add(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}),
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "AddScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "AddScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.Add(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.And(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.And(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.And(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.And(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "And_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.And(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.BitwiseClear(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseClear_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseClear", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.BitwiseClear(left[i], right[i]) != result[i]"}),
("VecTernOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseSelect_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["NextValueOp3"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}),
("VecTernOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseSelect_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["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()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
("VecTernOpTest.template", new Dictionary<string, string> { ["TestName"] = "BitwiseSelect_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "BitwiseSelect", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["Op3VectorType"] = "Vector64", ["Op3BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp3"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.BitwiseSelect(firstOp[i], secondOp[i], thirdOp[i]) != result[i]"}),
("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "CompareTest_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.CompareTest(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "CompareTest_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTest", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.CompareTest(left[i], right[i]) != result[i]"}),
("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"] = "LeadingSignCount_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}),
("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "LeadingSignCount_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}),
("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "LeadingSignCount_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "LeadingSignCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.CountLeadingSignBits(firstOp[i]) != result[i]"}),
("LoadUnOpTest.template", new Dictionary<string, string> { ["TestName"] = "LoadVector128_UInt16", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}),
("LoadUnOpTest.template", new Dictionary<string, string> { ["TestName"] = "LoadVector128_UInt32", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}),
("LoadUnOpTest.template", new Dictionary<string, string> { ["TestName"] = "LoadVector128_UInt64", ["Isa"] = "AdvSimd", ["Method"] = "LoadVector128", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "firstOp[i] != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Max(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Max(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Max(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Min(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Min(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Min(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Multiply(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Multiply(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Multiply(left[i], right[i]) != result[i]"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "MultiplyScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyScalar", ["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.Multiply(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "MultiplyScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "MultiplyScalar", ["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.Multiply(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Negate_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Negate_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Negate_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Negate_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Negate(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Negate_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Negate_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Negate_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Negate_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Negate(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("SimpleUnOpTest.template", new Dictionary<string, string> { ["TestName"] = "NegateScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "NegateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Negate(firstOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}),
+ ("SimpleUnOpTest.template", new Dictionary<string, string> { ["TestName"] = "NegateScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "NegateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Negate(firstOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Not(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Not(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Not(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Not(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Not_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Not", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Not(firstOp[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Or(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Or(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Or(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Or(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Or_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Or", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Or(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.OrNot(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "OrNot_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "OrNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.OrNot(left[i], right[i]) != result[i]"}),
("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "PopCount_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PopCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitCount(firstOp[i]) != result[i]"}),
("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "PopCount_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PopCount", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitCount(firstOp[i]) != result[i]"}),
("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "PopCount_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PopCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.BitCount(firstOp[i]) != result[i]"}),
("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "PopCount_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "PopCount", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.BitCount(firstOp[i]) != result[i]"}),
+ ("SimpleUnOpTest.template", new Dictionary<string, string> { ["TestName"] = "SqrtScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SqrtScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Sqrt(firstOp[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}),
+ ("SimpleUnOpTest.template", new Dictionary<string, string> { ["TestName"] = "SqrtScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SqrtScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Subtract(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Subtract(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Subtract(left[i], right[i]) != result[i]"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "SubtractScalar_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["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.Subtract(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "SubtractScalar_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.Subtract(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "SubtractScalar_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["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.Subtract(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "SubtractScalar_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "SubtractScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.Subtract(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector64_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector64_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Xor(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector64_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector64_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector64_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector64_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector64_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Xor(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector64_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector64_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector64_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector128_Byte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector128_Double", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Xor(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector128_Int16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector128_Int32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector128_Int64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector128_SByte", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector128_Single", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Xor(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector128_UInt16", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector128_UInt32", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Xor_Vector128_UInt64", ["Isa"] = "AdvSimd", ["LoadIsa"] = "AdvSimd", ["Method"] = "Xor", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateIterResult"] = "Helpers.Xor(left[i], right[i]) != result[i]"}),
};
private static readonly (string templateFileName, Dictionary<string, string> templateData)[] AdvSimd_Arm64Inputs = new []
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "CompareTestScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTestScalar", ["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.CompareTest(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}),
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "CompareTestScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTestScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.CompareTest(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}),
("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "CompareTestScalar_Vector64_UInt64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "CompareTestScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "UInt64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "UInt64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateFirstResult"] = "Helpers.CompareTest(left[0], right[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}),
- ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ReverseElementBits_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}),
- ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ReverseElementBits_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}),
- ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ReverseElementBits_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}),
- ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ReverseElementBits_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Divide_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Divide", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Divide(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Divide_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Divide", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Divide(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Divide_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Divide", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Divide(left[i], right[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Max_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Max", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Max(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "MaxScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxScalar", ["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.Max(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "MaxScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MaxScalar", ["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.Max(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Min_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Min", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Min(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "MinScalar_Vector64_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinScalar", ["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.Min(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != 0"}),
+ ("SimpleBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "MinScalar_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "MinScalar", ["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.Min(left[0], right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != 0"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Multiply_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Multiply", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Multiply(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Negate_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Negate(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Negate_Vector128_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Negate", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateIterResult"] = "Helpers.Negate(firstOp[i]) != result[i]"}),
+ ("SimpleUnOpTest.template", new Dictionary<string, string> { ["TestName"] = "NegateScalar_Vector64_Int64", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "NegateScalar", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int64", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int64", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()", ["ValidateFirstResult"] = "Helpers.Negate(firstOp[0]) != result[0]", ["ValidateRemainingResults"] = "result[i] != 0"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ReverseElementBits_Vector128_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ReverseElementBits_Vector128_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ReverseElementBits_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "ReverseElementBits_Vector64_SByte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "ReverseElementBits", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "SByte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["ValidateIterResult"] = "Helpers.ReverseElementBits(firstOp[i]) != result[i]"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Sqrt_Vector64_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Sqrt", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Sqrt_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Sqrt", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Sqrt(firstOp[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("SimpleVecOpTest.template", new Dictionary<string, string> { ["TestName"] = "Sqrt_Vector128_Single", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Sqrt", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["ValidateIterResult"] = "BitConverter.SingleToInt32Bits(Helpers.Sqrt(firstOp[i])) != BitConverter.SingleToInt32Bits(result[i])"}),
+ ("VecBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "Subtract_Vector128_Double", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "Subtract", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateIterResult"] = "BitConverter.DoubleToInt64Bits(Helpers.Subtract(left[i], right[i])) != BitConverter.DoubleToInt64Bits(result[i])"}),
("VecPairBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "TransposeEven_Vector64_Byte", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Byte", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Byte", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Byte", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetByte()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}),
("VecPairBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "TransposeEven_Vector64_Int16", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}),
("VecPairBinOpTest.template", new Dictionary<string, string> { ["TestName"] = "TransposeEven_Vector64_Int32", ["Isa"] = "AdvSimd.Arm64", ["LoadIsa"] = "AdvSimd", ["Method"] = "TransposeEven", ["RetVectorType"] = "Vector64", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector64", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector64", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "8", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateEntry"] = "result[index] != left[i] || result[++index] != right[i]"}),
return (ulong)result;
}
+ public static sbyte And(sbyte op1, sbyte op2) => (sbyte)(op1 & op2);
+
+ public static sbyte BitwiseClear(sbyte op1, sbyte op2) => (sbyte)(op1 & ~op2);
+
public static sbyte BitwiseSelect(sbyte op1, sbyte op2, sbyte op3)
{
ulong result = 0;
return (sbyte)result;
}
+ public static sbyte Not(sbyte op1) => (sbyte)(~op1);
+
+ public static sbyte Or(sbyte op1, sbyte op2) => (sbyte)(op1 | op2);
+
+ public static sbyte OrNot(sbyte op1, sbyte op2) => (sbyte)(op1 | ~op2);
+
+ public static sbyte Xor(sbyte op1, sbyte op2) => (sbyte)(op1 ^ op2);
+
+ public static byte And(byte op1, byte op2) => (byte)(op1 & op2);
+
+ public static byte BitwiseClear(byte op1, byte op2) => (byte)(op1 & ~op2);
+
public static byte BitwiseSelect(byte op1, byte op2, byte op3)
{
ulong result = 0;
return (byte)result;
}
+ public static byte Not(byte op1) => (byte)(~op1);
+
+ public static byte Or(byte op1, byte op2) => (byte)(op1 | op2);
+
+ public static byte OrNot(byte op1, byte op2) => (byte)(op1 | ~op2);
+
+ public static byte Xor(byte op1, byte op2) => (byte)(op1 ^ op2);
+
+ public static short And(short op1, short op2) => (short)(op1 & op2);
+
+ public static short BitwiseClear(short op1, short op2) => (short)(op1 & ~op2);
+
public static short BitwiseSelect(short op1, short op2, short op3)
{
ulong result = 0;
return (short)result;
}
+ public static short Not(short op1) => (short)(~op1);
+
+ public static short Or(short op1, short op2) => (short)(op1 | op2);
+
+ public static short OrNot(short op1, short op2) => (short)(op1 | ~op2);
+
+ public static short Xor(short op1, short op2) => (short)(op1 ^ op2);
+
+ public static ushort And(ushort op1, ushort op2) => (ushort)(op1 & op2);
+
+ public static ushort BitwiseClear(ushort op1, ushort op2) => (ushort)(op1 & ~op2);
+
public static ushort BitwiseSelect(ushort op1, ushort op2, ushort op3)
{
ulong result = 0;
return (ushort)result;
}
+ public static ushort Not(ushort op1) => (ushort)(~op1);
+
+ public static ushort Or(ushort op1, ushort op2) => (ushort)(op1 | op2);
+
+ public static ushort OrNot(ushort op1, ushort op2) => (ushort)(op1 | ~op2);
+
+ public static ushort Xor(ushort op1, ushort op2) => (ushort)(op1 ^ op2);
+
+ public static int And(int op1, int op2) => (int)(op1 & op2);
+
+ public static int BitwiseClear(int op1, int op2) => (int)(op1 & ~op2);
+
public static int BitwiseSelect(int op1, int op2, int op3)
{
ulong result = 0;
return (int)result;
}
+ public static int Not(int op1) => (int)(~op1);
+
+ public static int Or(int op1, int op2) => (int)(op1 | op2);
+
+ public static int OrNot(int op1, int op2) => (int)(op1 | ~op2);
+
+ public static int Xor(int op1, int op2) => (int)(op1 ^ op2);
+
+ public static uint And(uint op1, uint op2) => (uint)(op1 & op2);
+
+ public static uint BitwiseClear(uint op1, uint op2) => (uint)(op1 & ~op2);
+
public static uint BitwiseSelect(uint op1, uint op2, uint op3)
{
ulong result = 0;
return (uint)result;
}
+ public static uint Not(uint op1) => (uint)(~op1);
+
+ public static uint Or(uint op1, uint op2) => (uint)(op1 | op2);
+
+ public static uint OrNot(uint op1, uint op2) => (uint)(op1 | ~op2);
+
+ public static uint Xor(uint op1, uint op2) => (uint)(op1 ^ op2);
+
+ public static long And(long op1, long op2) => (long)(op1 & op2);
+
+ public static long BitwiseClear(long op1, long op2) => (long)(op1 & ~op2);
+
public static long BitwiseSelect(long op1, long op2, long op3)
{
ulong result = 0;
return (long)result;
}
+ public static long Not(long op1) => (long)(~op1);
+
+ public static long Or(long op1, long op2) => (long)(op1 | op2);
+
+ public static long OrNot(long op1, long op2) => (long)(op1 | ~op2);
+
+ public static long Xor(long op1, long op2) => (long)(op1 ^ op2);
+
+ public static ulong And(ulong op1, ulong op2) => (ulong)(op1 & op2);
+
+ public static ulong BitwiseClear(ulong op1, ulong op2) => (ulong)(op1 & ~op2);
+
public static ulong BitwiseSelect(ulong op1, ulong op2, ulong op3)
{
ulong result = 0;
return (ulong)result;
}
- public static float BitwiseSelect(float op1, float op2, float op3) => BitConverter.Int32BitsToSingle(BitwiseSelect(BitConverter.SingleToInt32Bits(op1), BitConverter.SingleToInt32Bits(op2), BitConverter.SingleToInt32Bits(op3)));
+ public static ulong Not(ulong op1) => (ulong)(~op1);
+
+ public static ulong Or(ulong op1, ulong op2) => (ulong)(op1 | op2);
+
+ public static ulong OrNot(ulong op1, ulong op2) => (ulong)(op1 | ~op2);
+
+ public static ulong Xor(ulong op1, ulong op2) => (ulong)(op1 ^ op2);
+
+ public static float Not(float op1) => BitConverter.Int32BitsToSingle(~BitConverter.SingleToInt32Bits(op1));
+
+ public static double Not(double op1) => BitConverter.Int64BitsToDouble(~BitConverter.DoubleToInt64Bits(op1));
+
+ public static float And(float op1, float op2) => BitConverter.Int32BitsToSingle(And(BitConverter.SingleToInt32Bits(op1), BitConverter.SingleToInt32Bits(op2)));
+ public static double And(double op1, double op2) => BitConverter.Int64BitsToDouble(And(BitConverter.DoubleToInt64Bits(op1), BitConverter.DoubleToInt64Bits(op2)));
+
+ public static float BitwiseClear(float op1, float op2) => BitConverter.Int32BitsToSingle(BitwiseClear(BitConverter.SingleToInt32Bits(op1), BitConverter.SingleToInt32Bits(op2)));
+
+ public static double BitwiseClear(double op1, double op2) => BitConverter.Int64BitsToDouble(BitwiseClear(BitConverter.DoubleToInt64Bits(op1), BitConverter.DoubleToInt64Bits(op2)));
+
+ public static float Or(float op1, float op2) => BitConverter.Int32BitsToSingle(Or(BitConverter.SingleToInt32Bits(op1), BitConverter.SingleToInt32Bits(op2)));
+
+ public static double Or(double op1, double op2) => BitConverter.Int64BitsToDouble(Or(BitConverter.DoubleToInt64Bits(op1), BitConverter.DoubleToInt64Bits(op2)));
+
+ public static float OrNot(float op1, float op2) => BitConverter.Int32BitsToSingle(OrNot(BitConverter.SingleToInt32Bits(op1), BitConverter.SingleToInt32Bits(op2)));
+
+ public static double OrNot(double op1, double op2) => BitConverter.Int64BitsToDouble(OrNot(BitConverter.DoubleToInt64Bits(op1), BitConverter.DoubleToInt64Bits(op2)));
+
+ public static float Xor(float op1, float op2) => BitConverter.Int32BitsToSingle(Xor(BitConverter.SingleToInt32Bits(op1), BitConverter.SingleToInt32Bits(op2)));
+
+ public static double Xor(double op1, double op2) => BitConverter.Int64BitsToDouble(Xor(BitConverter.DoubleToInt64Bits(op1), BitConverter.DoubleToInt64Bits(op2)));
+
+ public static float BitwiseSelect(float op1, float op2, float op3) => BitConverter.Int32BitsToSingle(BitwiseSelect(BitConverter.SingleToInt32Bits(op1), BitConverter.SingleToInt32Bits(op2), BitConverter.SingleToInt32Bits(op3)));
public static double BitwiseSelect(double op1, double op2, double op3) => BitConverter.Int64BitsToDouble(BitwiseSelect(BitConverter.DoubleToInt64Bits(op1), BitConverter.DoubleToInt64Bits(op2), BitConverter.DoubleToInt64Bits(op3)));
public static sbyte CompareEqual(sbyte left, sbyte right)
}
public static byte Abs(sbyte value) => value < 0 ? (byte)-value : (byte)value;
+
public static ushort Abs(short value) => value < 0 ? (ushort)-value : (ushort)value;
+
public static uint Abs(int value) => value < 0 ? (uint)-value : (uint)value;
+
public static ulong Abs(long value) => value < 0 ? (ulong)-value : (ulong)value;
+
public static float Abs(float value) => Math.Abs(value);
+
public static double Abs(double value) => Math.Abs(value);
+ public static float Divide(float op1, float op2) => op1 / op2;
+
+ public static double Divide(double op1, double op2) => op1 / op2;
+
+ public static float Sqrt(float value) => MathF.Sqrt(value);
+
+ public static double Sqrt(double value) => Math.Sqrt(value);
+
public static byte AbsoluteDifference(sbyte left, sbyte right) => (byte)Math.Abs((long)left - (long)right);
+
public static ushort AbsoluteDifference(short left, short right) => (ushort)Math.Abs((long)left - (long)right);
+
public static uint AbsoluteDifference(int left, int right) => (uint)Math.Abs((long)left - (long)right);
+
public static byte AbsoluteDifference(byte left, byte right) => (byte)Math.Abs((long)left - (long)right);
+
public static ushort AbsoluteDifference(ushort left, ushort right) => (ushort)Math.Abs((long)left - (long)right);
+
public static uint AbsoluteDifference(uint left, uint right) => (uint)Math.Abs((long)left - (long)right);
+
public static float AbsoluteDifference(float left, float right) => Math.Abs(left - right);
+
public static double AbsoluteDifference(double left, double right) => Math.Abs(left - right);
- public static sbyte Add(sbyte left, sbyte right) => (sbyte)(left + right);
- public static byte Add(byte left, byte right) => (byte)(left + right);
- public static short Add(short left, short right) => (short)(left + right);
- public static ushort Add(ushort left, ushort right) => (ushort)(left + right);
- public static int Add(int left, int right) => (int)(left + right);
- public static uint Add(uint left, uint right) => (uint)(left + right);
- public static long Add(long left, long right) => (long)(left + right);
- public static ulong Add(ulong left, ulong right) => (ulong)(left + right);
- public static float Add(float left, float right) => (float)(left + right);
- public static double Add(double left, double right) => (double)(left + right);
+ public static sbyte Add(sbyte op1, sbyte op2) => (sbyte)(op1 + op2);
+
+ public static sbyte Max(sbyte op1, sbyte op2) => Math.Max(op1, op2);
+
+ public static sbyte Min(sbyte op1, sbyte op2) => Math.Min(op1, op2);
+
+ public static sbyte Multiply(sbyte op1, sbyte op2) => (sbyte)(op1 * op2);
+
+ public static sbyte Subtract(sbyte op1, sbyte op2) => (sbyte)(op1 - op2);
+
+ public static byte Add(byte op1, byte op2) => (byte)(op1 + op2);
+
+ public static byte Max(byte op1, byte op2) => Math.Max(op1, op2);
+
+ public static byte Min(byte op1, byte op2) => Math.Min(op1, op2);
+
+ public static byte Multiply(byte op1, byte op2) => (byte)(op1 * op2);
+
+ public static byte Subtract(byte op1, byte op2) => (byte)(op1 - op2);
+
+ public static short Add(short op1, short op2) => (short)(op1 + op2);
+
+ public static short Max(short op1, short op2) => Math.Max(op1, op2);
+
+ public static short Min(short op1, short op2) => Math.Min(op1, op2);
+
+ public static short Multiply(short op1, short op2) => (short)(op1 * op2);
+
+ public static short Subtract(short op1, short op2) => (short)(op1 - op2);
+
+ public static ushort Add(ushort op1, ushort op2) => (ushort)(op1 + op2);
+
+ public static ushort Max(ushort op1, ushort op2) => Math.Max(op1, op2);
+
+ public static ushort Min(ushort op1, ushort op2) => Math.Min(op1, op2);
+
+ public static ushort Multiply(ushort op1, ushort op2) => (ushort)(op1 * op2);
+
+ public static ushort Subtract(ushort op1, ushort op2) => (ushort)(op1 - op2);
+
+ public static int Add(int op1, int op2) => (int)(op1 + op2);
+
+ public static int Max(int op1, int op2) => Math.Max(op1, op2);
+
+ public static int Min(int op1, int op2) => Math.Min(op1, op2);
+
+ public static int Multiply(int op1, int op2) => (int)(op1 * op2);
+
+ public static int Subtract(int op1, int op2) => (int)(op1 - op2);
+
+ public static uint Add(uint op1, uint op2) => (uint)(op1 + op2);
+
+ public static uint Max(uint op1, uint op2) => Math.Max(op1, op2);
+
+ public static uint Min(uint op1, uint op2) => Math.Min(op1, op2);
+
+ public static uint Multiply(uint op1, uint op2) => (uint)(op1 * op2);
+
+ public static uint Subtract(uint op1, uint op2) => (uint)(op1 - op2);
+
+ public static long Add(long op1, long op2) => (long)(op1 + op2);
+
+ public static long Max(long op1, long op2) => Math.Max(op1, op2);
+
+ public static long Min(long op1, long op2) => Math.Min(op1, op2);
+
+ public static long Multiply(long op1, long op2) => (long)(op1 * op2);
+
+ public static long Subtract(long op1, long op2) => (long)(op1 - op2);
+
+ public static ulong Add(ulong op1, ulong op2) => (ulong)(op1 + op2);
+
+ public static ulong Max(ulong op1, ulong op2) => Math.Max(op1, op2);
+
+ public static ulong Min(ulong op1, ulong op2) => Math.Min(op1, op2);
+
+ public static ulong Multiply(ulong op1, ulong op2) => (ulong)(op1 * op2);
+
+ public static ulong Subtract(ulong op1, ulong op2) => (ulong)(op1 - op2);
+
+ public static float Add(float op1, float op2) => (float)(op1 + op2);
+
+ public static float Max(float op1, float op2) => Math.Max(op1, op2);
+
+ public static float Min(float op1, float op2) => Math.Min(op1, op2);
+
+ public static float Multiply(float op1, float op2) => (float)(op1 * op2);
+
+ public static float Subtract(float op1, float op2) => (float)(op1 - op2);
+
+ public static double Add(double op1, double op2) => (double)(op1 + op2);
+
+ public static double Max(double op1, double op2) => Math.Max(op1, op2);
+
+ public static double Min(double op1, double op2) => Math.Min(op1, op2);
+
+ public static double Multiply(double op1, double op2) => (double)(op1 * op2);
+
+ public static double Subtract(double op1, double op2) => (double)(op1 - op2);
+
+ public static sbyte Negate(sbyte op1) => (sbyte)(-op1);
+
+ public static short Negate(short op1) => (short)(-op1);
+
+ public static int Negate(int op1) => (int)(-op1);
+
+ public static long Negate(long op1) => (long)(-op1);
+
+ public static float Negate(float op1) => (float)(-op1);
+
+ public static double Negate(double op1) => (double)(-op1);
+
}
}
foreach (string typeName in new string[] { "sbyte", "byte", "short", "ushort", "int", "uint", "long", "ulong" })
{
#>
+ public static <#= typeName #> And(<#= typeName #> op1, <#= typeName #> op2) => (<#= typeName #>)(op1 & op2);
+
+ public static <#= typeName #> BitwiseClear(<#= typeName #> op1, <#= typeName #> op2) => (<#= typeName #>)(op1 & ~op2);
+
public static <#= typeName #> BitwiseSelect(<#= typeName #> op1, <#= typeName #> op2, <#= typeName #> op3)
{
ulong result = 0;
return (<#= typeName #>)result;
}
+ public static <#= typeName #> Not(<#= typeName #> op1) => (<#= typeName #>)(~op1);
+
+ public static <#= typeName #> Or(<#= typeName #> op1, <#= typeName #> op2) => (<#= typeName #>)(op1 | op2);
+
+ public static <#= typeName #> OrNot(<#= typeName #> op1, <#= typeName #> op2) => (<#= typeName #>)(op1 | ~op2);
+
+ public static <#= typeName #> Xor(<#= typeName #> op1, <#= typeName #> op2) => (<#= typeName #>)(op1 ^ op2);
+
<#
}
#>
- public static float BitwiseSelect(float op1, float op2, float op3) => BitConverter.Int32BitsToSingle(BitwiseSelect(BitConverter.SingleToInt32Bits(op1), BitConverter.SingleToInt32Bits(op2), BitConverter.SingleToInt32Bits(op3)));
+ public static float Not(float op1) => BitConverter.Int32BitsToSingle(~BitConverter.SingleToInt32Bits(op1));
+
+ public static double Not(double op1) => BitConverter.Int64BitsToDouble(~BitConverter.DoubleToInt64Bits(op1));
+
+<#
+ foreach (string helperName in new string[] { "And", "BitwiseClear", "Or", "OrNot", "Xor" })
+ {
+#>
+ public static float <#= helperName #>(float op1, float op2) => BitConverter.Int32BitsToSingle(<#= helperName #>(BitConverter.SingleToInt32Bits(op1), BitConverter.SingleToInt32Bits(op2)));
+ public static double <#= helperName #>(double op1, double op2) => BitConverter.Int64BitsToDouble(<#= helperName #>(BitConverter.DoubleToInt64Bits(op1), BitConverter.DoubleToInt64Bits(op2)));
+
+<#
+ }
+#>
+ public static float BitwiseSelect(float op1, float op2, float op3) => BitConverter.Int32BitsToSingle(BitwiseSelect(BitConverter.SingleToInt32Bits(op1), BitConverter.SingleToInt32Bits(op2), BitConverter.SingleToInt32Bits(op3)));
public static double BitwiseSelect(double op1, double op2, double op3) => BitConverter.Int64BitsToDouble(BitwiseSelect(BitConverter.DoubleToInt64Bits(op1), BitConverter.DoubleToInt64Bits(op2), BitConverter.DoubleToInt64Bits(op3)));
<#
{
#>
public static <#= type.unsigned #> Abs(<#= type.name #> value) => value < 0 ? (<#= type.unsigned #>)-value : (<#= type.unsigned #>)value;
+
<#
}
#>
public static float Abs(float value) => Math.Abs(value);
+
public static double Abs(double value) => Math.Abs(value);
+ public static float Divide(float op1, float op2) => op1 / op2;
+
+ public static double Divide(double op1, double op2) => op1 / op2;
+
+ public static float Sqrt(float value) => MathF.Sqrt(value);
+
+ public static double Sqrt(double value) => Math.Sqrt(value);
+
<#
foreach (var type in new[] { (name: "sbyte", unsigned: "byte"),
(name: "short", unsigned: "ushort"),
{
#>
public static <#= type.unsigned #> AbsoluteDifference(<#= type.name #> left, <#= type.name #> right) => (<#= type.unsigned #>)Math.Abs((long)left - (long)right);
+
<#
}
#>
public static float AbsoluteDifference(float left, float right) => Math.Abs(left - right);
+
public static double AbsoluteDifference(double left, double right) => Math.Abs(left - right);
<#
foreach (string typeName in new string[] { "sbyte", "byte", "short", "ushort", "int", "uint", "long", "ulong", "float", "double" })
{
#>
- public static <#= typeName #> Add(<#= typeName #> left, <#= typeName #> right) => (<#= typeName #>)(left + right);
+ public static <#= typeName #> Add(<#= typeName #> op1, <#= typeName #> op2) => (<#= typeName #>)(op1 + op2);
+
+ public static <#= typeName #> Max(<#= typeName #> op1, <#= typeName #> op2) => Math.Max(op1, op2);
+
+ public static <#= typeName #> Min(<#= typeName #> op1, <#= typeName #> op2) => Math.Min(op1, op2);
+
+ public static <#= typeName #> Multiply(<#= typeName #> op1, <#= typeName #> op2) => (<#= typeName #>)(op1 * op2);
+
+ public static <#= typeName #> Subtract(<#= typeName #> op1, <#= typeName #> op2) => (<#= typeName #>)(op1 - op2);
+
+<#
+ }
+
+ foreach (string typeName in new string[] { "sbyte", "short", "int", "long", "float", "double" })
+ {
+#>
+ public static <#= typeName #> Negate(<#= typeName #> op1) => (<#= typeName #>)(-op1);
+
<#
}
#>
public static Vector64<ulong> CompareTestScalar(Vector64<ulong> left, Vector64<ulong> right) { throw new PlatformNotSupportedException(); }
/// <summary>
+ /// float32x2_t vdiv_f32 (float32x2_t a, float32x2_t b)
+ /// A64: FDIV Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<float> Divide(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float64x2_t vdivq_f64 (float64x2_t a, float64x2_t b)
+ /// A64: FDIV Vd.2D, Vn.2D, Vm.2D
+ /// </summary>
+ public static Vector128<double> Divide(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32x4_t vdivq_f32 (float32x4_t a, float32x4_t b)
+ /// A64: FDIV Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<float> Divide(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float64x2_t vmaxq_f64 (float64x2_t a, float64x2_t b)
+ /// A64: FMAX Vd.2D, Vn.2D, Vm.2D
+ /// </summary>
+ public static Vector128<double> Max(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float64x1_t vmax_f64 (float64x1_t a, float64x1_t b)
+ /// A64: FMAX Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<double> MaxScalar(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32_t vmaxs_f32 (float32_t a, float32_t b)
+ /// A64: FMAX Sd, Sn, Sm
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<float> MaxScalar(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float64x2_t vminq_f64 (float64x2_t a, float64x2_t b)
+ /// A64: FMIN Vd.2D, Vn.2D, Vm.2D
+ /// </summary>
+ public static Vector128<double> Min(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float64x1_t vmin_f64 (float64x1_t a, float64x1_t b)
+ /// A64: FMIN Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<double> MinScalar(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32_t vmins_f32 (float32_t a, float32_t b)
+ /// A64: FMIN Sd, Sn, Sm
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<float> MinScalar(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float64x2_t vmulq_f64 (float64x2_t a, float64x2_t b)
+ /// A64: FMUL Vd.2D, Vn.2D, Vm.2D
+ /// </summary>
+ public static Vector128<double> Multiply(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float64x2_t vnegq_f64 (float64x2_t a)
+ /// A64: FNEG Vd.2D, Vn.2D
+ /// </summary>
+ public static Vector128<double> Negate(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int64x2_t vnegq_s64 (int64x2_t a)
+ /// A64: NEG Vd.2D, Vn.2D
+ /// </summary>
+ public static Vector128<long> Negate(Vector128<long> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int64x1_t vneg_s64 (int64x1_t a)
+ /// A64: NEG Dd, Dn
+ /// </summary>
+ public static Vector64<long> NegateScalar(Vector64<long> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32x2_t vsqrt_f32 (float32x2_t a)
+ /// A64: FSQRT Vd.2S, Vn.2S
+ /// </summary>
+ public static Vector64<float> Sqrt(Vector64<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float64x2_t vsqrtq_f64 (float64x2_t a)
+ /// A64: FSQRT Vd.2D, Vn.2D
+ /// </summary>
+ public static Vector128<double> Sqrt(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32x4_t vsqrtq_f32 (float32x4_t a)
+ /// A64: FSQRT Vd.4S, Vn.4S
+ /// </summary>
+ public static Vector128<float> Sqrt(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
/// float64x2_t vsubq_f64 (float64x2_t a, float64x2_t b)
/// A64: FSUB Vd.2D, Vn.2D, Vm.2D
/// </summary>
/// <summary>
/// uint8x8_t vand_u8 (uint8x8_t a, uint8x8_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<byte> And(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// float64x1_t vand_f64 (float64x1_t a, float64x1_t b)
- // /// A32: VAND Dd, Dn, Dm
- // /// A64: AND Vd, Vn, Vm
- // /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
- // /// </summary>
- // public static Vector64<double> And(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// float64x1_t vand_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VAND Dd, Dn, Dm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<double> And(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// int16x4_t vand_s16 (int16x4_t a, int16x4_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<short> And(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int32x2_t vand_s32(int32x2_t a, int32x2_t b)
+ /// int32x2_t vand_s32 (int32x2_t a, int32x2_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<int> And(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// int64x1_t vand_s64 (int64x1_t a, int64x1_t b)
- // /// A32: VAND Dd, Dn, Dm
- // /// A64: AND Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<long> And(Vector64<long> left, Vector64<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int64x1_t vand_s64 (int64x1_t a, int64x1_t b)
+ /// A32: VAND Dd, Dn, Dm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<long> And(Vector64<long> left, Vector64<long> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// int8x8_t vand_s8 (int8x8_t a, int8x8_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<sbyte> And(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// float32x2_t vand_f32 (float32x2_t a, float32x2_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector64<float> And(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint16x4_t vand_u16 (uint16x4_t a, uint16x4_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<ushort> And(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint32x2_t vand_u32 (uint32x2_t a, uint32x2_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<uint> And(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// uint64x1_t vand_u64 (uint64x1_t a, uint64x1_t b)
- // /// A32: VAND Dd, Dn, Dm
- // /// A64: AND Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<ulong> And(Vector64<ulong> left, Vector64<ulong> right) { throw new PlatformNotSupportedException(); }
-
/// <summary>
- /// uint8x16_t vand_u8 (uint8x16_t a, uint8x16_t b)
+ /// uint64x1_t vand_u64 (uint64x1_t a, uint64x1_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<ulong> And(Vector64<ulong> left, Vector64<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint8x16_t vandq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<byte> And(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// float64x2_t vand_f64 (float64x2_t a, float64x2_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// float64x2_t vandq_f64 (float64x2_t a, float64x2_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<double> And(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int16x8_t vand_s16 (int16x8_t a, int16x8_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// int16x8_t vandq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<short> And(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int32x4_t vand_s32(int32x4_t a, int32x4_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// int32x4_t vandq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<int> And(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int64x2_t vand_s64 (int64x2_t a, int64x2_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// int64x2_t vandq_s64 (int64x2_t a, int64x2_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<long> And(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int8x16_t vand_s8 (int8x16_t a, int8x16_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// int8x16_t vandq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<sbyte> And(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// float32x4_t vand_f32 (float32x4_t a, float32x4_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// float32x4_t vandq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<float> And(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint16x8_t vand_u16 (uint16x8_t a, uint16x8_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// uint16x8_t vandq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ushort> And(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint32x4_t vand_u32 (uint32x4_t a, uint32x4_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// uint32x4_t vandq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<uint> And(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint64x2_t vand_u64 (uint64x2_t a, uint64x2_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// uint64x2_t vandq_u64 (uint64x2_t a, uint64x2_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ulong> And(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint8x8_t vbic_u8 (uint8x8_t a, uint8x8_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector64<byte> AndNot(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<byte> BitwiseClear(Vector64<byte> value, Vector64<byte> mask) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// float64x1_t vbic_f64 (float64x1_t a, float64x1_t b)
- // /// A32: VBIC Dd, Dn, Dm
- // /// A64: BIC Vd, Vn, Vm
- // /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
- // /// </summary>
- // public static Vector64<double> AndNot(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// float64x1_t vbic_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VBIC Dd, Dn, Dm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<double> BitwiseClear(Vector64<double> value, Vector64<double> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
/// int16x4_t vbic_s16 (int16x4_t a, int16x4_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector64<short> AndNot(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<short> BitwiseClear(Vector64<short> value, Vector64<short> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int32x2_t vbic_s32(int32x2_t a, int32x2_t b)
+ /// int32x2_t vbic_s32 (int32x2_t a, int32x2_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector64<int> AndNot(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<int> BitwiseClear(Vector64<int> value, Vector64<int> mask) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// int64x1_t vbic_s64 (int64x1_t a, int64x1_t b)
- // /// A32: VBIC Dd, Dn, Dm
- // /// A64: BIC Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<long> AndNot(Vector64<long> left, Vector64<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int64x1_t vbic_s64 (int64x1_t a, int64x1_t b)
+ /// A32: VBIC Dd, Dn, Dm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<long> BitwiseClear(Vector64<long> value, Vector64<long> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
/// int8x8_t vbic_s8 (int8x8_t a, int8x8_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector64<sbyte> AndNot(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<sbyte> BitwiseClear(Vector64<sbyte> value, Vector64<sbyte> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
/// float32x2_t vbic_f32 (float32x2_t a, float32x2_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
- public static Vector64<float> AndNot(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<float> BitwiseClear(Vector64<float> value, Vector64<float> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint16x4_t vbic_u16 (uint16x4_t a, uint16x4_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector64<ushort> AndNot(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<ushort> BitwiseClear(Vector64<ushort> value, Vector64<ushort> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint32x2_t vbic_u32 (uint32x2_t a, uint32x2_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector64<uint> AndNot(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
-
- // /// <summary>
- // /// uint64x1_t vbic_u64 (uint64x1_t a, uint64x1_t b)
- // /// A32: VBIC Dd, Dn, Dm
- // /// A64: BIC Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<ulong> AndNot(Vector64<ulong> left, Vector64<ulong> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<uint> BitwiseClear(Vector64<uint> value, Vector64<uint> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint8x16_t vbic_u8 (uint8x16_t a, uint8x16_t b)
+ /// uint64x1_t vbic_u64 (uint64x1_t a, uint64x1_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector128<byte> AndNot(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<ulong> BitwiseClear(Vector64<ulong> value, Vector64<ulong> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// float64x2_t vbic_f64 (float64x2_t a, float64x2_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// uint8x16_t vbicq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<byte> BitwiseClear(Vector128<byte> value, Vector128<byte> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float64x2_t vbicq_f64 (float64x2_t a, float64x2_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
- public static Vector128<double> AndNot(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> BitwiseClear(Vector128<double> value, Vector128<double> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int16x8_t vbic_s16 (int16x8_t a, int16x8_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// int16x8_t vbicq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<short> AndNot(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<short> BitwiseClear(Vector128<short> value, Vector128<short> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int32x4_t vbic_s32(int32x4_t a, int32x4_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// int32x4_t vbicq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<int> AndNot(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<int> BitwiseClear(Vector128<int> value, Vector128<int> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int64x2_t vbic_s64 (int64x2_t a, int64x2_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// int64x2_t vbicq_s64 (int64x2_t a, int64x2_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<long> AndNot(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<long> BitwiseClear(Vector128<long> value, Vector128<long> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int8x16_t vbic_s8 (int8x16_t a, int8x16_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// int8x16_t vbicq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<sbyte> AndNot(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> BitwiseClear(Vector128<sbyte> value, Vector128<sbyte> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// float32x4_t vbic_f32 (float32x4_t a, float32x4_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// float32x4_t vbicq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
- public static Vector128<float> AndNot(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> BitwiseClear(Vector128<float> value, Vector128<float> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint16x8_t vbic_u16 (uint16x8_t a, uint16x8_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// uint16x8_t vbicq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<ushort> AndNot(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ushort> BitwiseClear(Vector128<ushort> value, Vector128<ushort> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint32x4_t vbic_u32 (uint32x4_t a, uint32x4_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// uint32x4_t vbicq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<uint> AndNot(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<uint> BitwiseClear(Vector128<uint> value, Vector128<uint> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint64x2_t vbic_u64 (uint64x2_t a, uint64x2_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// uint64x2_t vbicq_u64 (uint64x2_t a, uint64x2_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<ulong> AndNot(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ulong> BitwiseClear(Vector128<ulong> value, Vector128<ulong> mask) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint8x8_t vbsl_u8 (uint8x8_t a, uint8x8_t b, uint8x8_t c)
public static Vector128<uint> CompareTest(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
/// <summary>
+ /// float64x1_t vdiv_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VDIV.F64 Dd, Dn, Dm
+ /// A64: FDIV Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<double> DivideScalar(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32_t vdivs_f32 (float32_t a, float32_t b)
+ /// A32: VDIV.F32 Sd, Sn, Sm
+ /// A64: FDIV Sd, Sn, Sm
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<float> DivideScalar(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
/// int16x4_t vcls_s16 (int16x4_t a)
/// A32: VCLS.S16 Dd, Dm
/// A64: CLS Vd.4H, Vn.4H
public static unsafe Vector128<ulong> LoadVector128(ulong* address) { throw new PlatformNotSupportedException(); }
/// <summary>
+ /// uint8x8_t vmax_u8 (uint8x8_t a, uint8x8_t b)
+ /// A32: VMAX.U8 Dd, Dn, Dm
+ /// A64: UMAX Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<byte> Max(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int16x4_t vmax_s16 (int16x4_t a, int16x4_t b)
+ /// A32: VMAX.S16 Dd, Dn, Dm
+ /// A64: SMAX Vd.4H, Vn.4H, Vm.4H
+ /// </summary>
+ public static Vector64<short> Max(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int32x2_t vmax_s32 (int32x2_t a, int32x2_t b)
+ /// A32: VMAX.S32 Dd, Dn, Dm
+ /// A64: SMAX Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<int> Max(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int8x8_t vmax_s8 (int8x8_t a, int8x8_t b)
+ /// A32: VMAX.S8 Dd, Dn, Dm
+ /// A64: SMAX Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<sbyte> Max(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32x2_t vmax_f32 (float32x2_t a, float32x2_t b)
+ /// A32: VMAX.F32 Dd, Dn, Dm
+ /// A64: FMAX Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<float> Max(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint16x4_t vmax_u16 (uint16x4_t a, uint16x4_t b)
+ /// A32: VMAX.U16 Dd, Dn, Dm
+ /// A64: UMAX Vd.4H, Vn.4H, Vm.4H
+ /// </summary>
+ public static Vector64<ushort> Max(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint32x2_t vmax_u32 (uint32x2_t a, uint32x2_t b)
+ /// A32: VMAX.U32 Dd, Dn, Dm
+ /// A64: UMAX Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<uint> Max(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint8x16_t vmaxq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VMAX.U8 Qd, Qn, Qm
+ /// A64: UMAX Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<byte> Max(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int16x8_t vmaxq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VMAX.S16 Qd, Qn, Qm
+ /// A64: SMAX Vd.8H, Vn.8H, Vm.8H
+ /// </summary>
+ public static Vector128<short> Max(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int32x4_t vmaxq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VMAX.S32 Qd, Qn, Qm
+ /// A64: SMAX Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<int> Max(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int8x16_t vmaxq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VMAX.S8 Qd, Qn, Qm
+ /// A64: SMAX Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<sbyte> Max(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32x4_t vmaxq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VMAX.F32 Qd, Qn, Qm
+ /// A64: FMAX Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<float> Max(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint16x8_t vmaxq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VMAX.U16 Qd, Qn, Qm
+ /// A64: UMAX Vd.8H, Vn.8H, Vm.8H
+ /// </summary>
+ public static Vector128<ushort> Max(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint32x4_t vmaxq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VMAX.U32 Qd, Qn, Qm
+ /// A64: UMAX Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<uint> Max(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint8x8_t vmin_u8 (uint8x8_t a, uint8x8_t b)
+ /// A32: VMIN.U8 Dd, Dn, Dm
+ /// A64: UMIN Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<byte> Min(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int16x4_t vmin_s16 (int16x4_t a, int16x4_t b)
+ /// A32: VMIN.S16 Dd, Dn, Dm
+ /// A64: SMIN Vd.4H, Vn.4H, Vm.4H
+ /// </summary>
+ public static Vector64<short> Min(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int32x2_t vmin_s32 (int32x2_t a, int32x2_t b)
+ /// A32: VMIN.S32 Dd, Dn, Dm
+ /// A64: SMIN Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<int> Min(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int8x8_t vmin_s8 (int8x8_t a, int8x8_t b)
+ /// A32: VMIN.S8 Dd, Dn, Dm
+ /// A64: SMIN Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<sbyte> Min(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32x2_t vmin_f32 (float32x2_t a, float32x2_t b)
+ /// A32: VMIN.F32 Dd, Dn, Dm
+ /// A64: FMIN Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<float> Min(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint16x4_t vmin_u16 (uint16x4_t a, uint16x4_t b)
+ /// A32: VMIN.U16 Dd, Dn, Dm
+ /// A64: UMIN Vd.4H, Vn.4H, Vm.4H
+ /// </summary>
+ public static Vector64<ushort> Min(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint32x2_t vmin_u32 (uint32x2_t a, uint32x2_t b)
+ /// A32: VMIN.U32 Dd, Dn, Dm
+ /// A64: UMIN Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<uint> Min(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint8x16_t vminq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VMIN.U8 Qd, Qn, Qm
+ /// A64: UMIN Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<byte> Min(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int16x8_t vminq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VMIN.S16 Qd, Qn, Qm
+ /// A64: SMIN Vd.8H, Vn.8H, Vm.8H
+ /// </summary>
+ public static Vector128<short> Min(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int32x4_t vminq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VMIN.S32 Qd, Qn, Qm
+ /// A64: SMIN Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<int> Min(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int8x16_t vminq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VMIN.S8 Qd, Qn, Qm
+ /// A64: SMIN Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<sbyte> Min(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32x4_t vminq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VMIN.F32 Qd, Qn, Qm
+ /// A64: FMIN Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<float> Min(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint16x8_t vminq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VMIN.U16 Qd, Qn, Qm
+ /// A64: UMIN Vd.8H, Vn.8H, Vm.8H
+ /// </summary>
+ public static Vector128<ushort> Min(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint32x4_t vminq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VMIN.U32 Qd, Qn, Qm
+ /// A64: UMIN Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<uint> Min(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint8x8_t vmul_u8 (uint8x8_t a, uint8x8_t b)
+ /// A32: VMUL.I8 Dd, Dn, Dm
+ /// A64: MUL Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<byte> Multiply(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int16x4_t vmul_s16 (int16x4_t a, int16x4_t b)
+ /// A32: VMUL.I16 Dd, Dn, Dm
+ /// A64: MUL Vd.4H, Vn.4H, Vm.4H
+ /// </summary>
+ public static Vector64<short> Multiply(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int32x2_t vmul_s32 (int32x2_t a, int32x2_t b)
+ /// A32: VMUL.I32 Dd, Dn, Dm
+ /// A64: MUL Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<int> Multiply(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int8x8_t vmul_s8 (int8x8_t a, int8x8_t b)
+ /// A32: VMUL.I8 Dd, Dn, Dm
+ /// A64: MUL Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<sbyte> Multiply(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32x2_t vmul_f32 (float32x2_t a, float32x2_t b)
+ /// A32: VMUL.F32 Dd, Dn, Dm
+ /// A64: FMUL Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<float> Multiply(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint16x4_t vmul_u16 (uint16x4_t a, uint16x4_t b)
+ /// A32: VMUL.I16 Dd, Dn, Dm
+ /// A64: MUL Vd.4H, Vn.4H, Vm.4H
+ /// </summary>
+ public static Vector64<ushort> Multiply(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint32x2_t vmul_u32 (uint32x2_t a, uint32x2_t b)
+ /// A32: VMUL.I32 Dd, Dn, Dm
+ /// A64: MUL Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<uint> Multiply(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint8x16_t vmulq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VMUL.I8 Qd, Qn, Qm
+ /// A64: MUL Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<byte> Multiply(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int16x8_t vmulq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VMUL.I16 Qd, Qn, Qm
+ /// A64: MUL Vd.8H, Vn.8H, Vm.8H
+ /// </summary>
+ public static Vector128<short> Multiply(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int32x4_t vmulq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VMUL.I32 Qd, Qn, Qm
+ /// A64: MUL Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<int> Multiply(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int8x16_t vmulq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VMUL.I8 Qd, Qn, Qm
+ /// A64: MUL Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<sbyte> Multiply(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32x4_t vmulq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VMUL.F32 Qd, Qn, Qm
+ /// A64: FMUL Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<float> Multiply(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint16x8_t vmulq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VMUL.I16 Qd, Qn, Qm
+ /// A64: MUL Vd.8H, Vn.8H, Vm.8H
+ /// </summary>
+ public static Vector128<ushort> Multiply(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint32x4_t vmulq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VMUL.I32 Qd, Qn, Qm
+ /// A64: MUL Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<uint> Multiply(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float64x1_t vmul_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VMUL.F64 Dd, Dn, Dm
+ /// A64: FMUL Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<double> MultiplyScalar(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32_t vmuls_f32 (float32_t a, float32_t b)
+ /// A32: VMUL.F32 Sd, Sn, Sm
+ /// A64: FMUL Sd, Sn, Sm
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<float> MultiplyScalar(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int16x4_t vneg_s16 (int16x4_t a)
+ /// A32: VNEG.S16 Dd, Dm
+ /// A64: NEG Vd.4H, Vn.4H
+ /// </summary>
+ public static Vector64<short> Negate(Vector64<short> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int32x2_t vneg_s32 (int32x2_t a)
+ /// A32: VNEG.S32 Dd, Dm
+ /// A64: NEG Vd.2S, Vn.2S
+ /// </summary>
+ public static Vector64<int> Negate(Vector64<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int8x8_t vneg_s8 (int8x8_t a)
+ /// A32: VNEG.S8 Dd, Dm
+ /// A64: NEG Vd.8B, Vn.8B
+ /// </summary>
+ public static Vector64<sbyte> Negate(Vector64<sbyte> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32x2_t vneg_f32 (float32x2_t a)
+ /// A32: VNEG.F32 Dd, Dm
+ /// A64: FNEG Vd.2S, Vn.2S
+ /// </summary>
+ public static Vector64<float> Negate(Vector64<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int16x8_t vnegq_s16 (int16x8_t a)
+ /// A32: VNEG.S16 Qd, Qm
+ /// A64: NEG Vd.8H, Vn.8H
+ /// </summary>
+ public static Vector128<short> Negate(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int32x4_t vnegq_s32 (int32x4_t a)
+ /// A32: VNEG.S32 Qd, Qm
+ /// A64: NEG Vd.4S, Vn.4S
+ /// </summary>
+ public static Vector128<int> Negate(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int8x16_t vnegq_s8 (int8x16_t a)
+ /// A32: VNEG.S8 Qd, Qm
+ /// A64: NEG Vd.16B, Vn.16B
+ /// </summary>
+ public static Vector128<sbyte> Negate(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32x4_t vnegq_f32 (float32x4_t a)
+ /// A32: VNEG.F32 Qd, Qm
+ /// A64: FNEG Vd.4S, Vn.4S
+ /// </summary>
+ public static Vector128<float> Negate(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float64x1_t vneg_f64 (float64x1_t a)
+ /// A32: VNEG.F64 Dd, Dm
+ /// A64: FNEG Dd, Dn
+ /// </summary>
+ public static Vector64<double> NegateScalar(Vector64<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32_t vnegs_f32 (float32_t a)
+ /// A32: VNEG.F32 Sd, Sm
+ /// A64: FNEG Sd, Sn
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<float> NegateScalar(Vector64<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
/// uint8x8_t vmvn_u8 (uint8x8_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// </summary>
public static Vector64<byte> Not(Vector64<byte> value) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// float64x1_t vmvn_f64 (float64x1_t a)
- // /// A32: VMVN Dd, Dn, Dm
- // /// A64: MVN Vd, Vn, Vm
- // /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
- // /// </summary>
- // public static Vector64<double> Not(Vector64<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// float64x1_t vmvn_f64 (float64x1_t a)
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<double> Not(Vector64<double> value) { throw new PlatformNotSupportedException(); }
/// <summary>
/// int16x4_t vmvn_s16 (int16x4_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// </summary>
public static Vector64<short> Not(Vector64<short> value) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int32x2_t vmvn_s32(int32x2_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// int32x2_t vmvn_s32 (int32x2_t a)
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// </summary>
public static Vector64<int> Not(Vector64<int> value) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// int64x1_t vmvn_s64 (int64x1_t a)
- // /// A32: VMVN Dd, Dn, Dm
- // /// A64: MVN Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<long> Not(Vector64<long> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int64x1_t vmvn_s64 (int64x1_t a)
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
+ /// </summary>
+ public static Vector64<long> Not(Vector64<long> value) { throw new PlatformNotSupportedException(); }
/// <summary>
/// int8x8_t vmvn_s8 (int8x8_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// </summary>
public static Vector64<sbyte> Not(Vector64<sbyte> value) { throw new PlatformNotSupportedException(); }
/// <summary>
/// float32x2_t vmvn_f32 (float32x2_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector64<float> Not(Vector64<float> value) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint16x4_t vmvn_u16 (uint16x4_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// </summary>
public static Vector64<ushort> Not(Vector64<ushort> value) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint32x2_t vmvn_u32 (uint32x2_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// </summary>
public static Vector64<uint> Not(Vector64<uint> value) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// uint64x1_t vmvn_u64 (uint64x1_t a)
- // /// A32: VMVN Dd, Dn, Dm
- // /// A64: MVN Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<ulong> Not(Vector64<ulong> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// uint64x1_t vmvn_u64 (uint64x1_t a)
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
+ /// </summary>
+ public static Vector64<ulong> Not(Vector64<ulong> value) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint8x16_t vmvn_u8 (uint8x16_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// uint8x16_t vmvnq_u8 (uint8x16_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<byte> Not(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// float64x2_t vmvn_f64 (float64x2_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// float64x2_t vmvnq_f64 (float64x2_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<double> Not(Vector128<double> value) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int16x8_t vmvn_s16 (int16x8_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// int16x8_t vmvnq_s16 (int16x8_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<short> Not(Vector128<short> value) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int32x4_t vmvn_s32(int32x4_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// int32x4_t vmvnq_s32 (int32x4_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<int> Not(Vector128<int> value) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int64x2_t vmvn_s64 (int64x2_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// int64x2_t vmvnq_s64 (int64x2_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<long> Not(Vector128<long> value) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int8x16_t vmvn_s8 (int8x16_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// int8x16_t vmvnq_s8 (int8x16_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<sbyte> Not(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// float32x4_t vmvn_f32 (float32x4_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// float32x4_t vmvnq_f32 (float32x4_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<float> Not(Vector128<float> value) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint16x8_t vmvn_u16 (uint16x8_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// uint16x8_t vmvnq_u16 (uint16x8_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<ushort> Not(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint32x4_t vmvn_u32 (uint32x4_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// uint32x4_t vmvnq_u32 (uint32x4_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<uint> Not(Vector128<uint> value) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint64x2_t vmvn_u64 (uint64x2_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// uint64x2_t vmvnq_u64 (uint64x2_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<ulong> Not(Vector128<ulong> value) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint8x8_t vorr_u8 (uint8x8_t a, uint8x8_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<byte> Or(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// float64x1_t vorr_f64 (float64x1_t a, float64x1_t b)
- // /// A32: VORR Dd, Dn, Dm
- // /// A64: ORR Vd, Vn, Vm
- // /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
- // /// </summary>
- // public static Vector64<double> Or(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// float64x1_t vorr_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VORR Dd, Dn, Dm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<double> Or(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// int16x4_t vorr_s16 (int16x4_t a, int16x4_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<short> Or(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int32x2_t vorr_s32(int32x2_t a, int32x2_t b)
+ /// int32x2_t vorr_s32 (int32x2_t a, int32x2_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<int> Or(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// int64x1_t vorr_s64 (int64x1_t a, int64x1_t b)
- // /// A32: VORR Dd, Dn, Dm
- // /// A64: ORR Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<long> Or(Vector64<long> left, Vector64<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int64x1_t vorr_s64 (int64x1_t a, int64x1_t b)
+ /// A32: VORR Dd, Dn, Dm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<long> Or(Vector64<long> left, Vector64<long> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// int8x8_t vorr_s8 (int8x8_t a, int8x8_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<sbyte> Or(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// float32x2_t vorr_f32 (float32x2_t a, float32x2_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector64<float> Or(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint16x4_t vorr_u16 (uint16x4_t a, uint16x4_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<ushort> Or(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint32x2_t vorr_u32 (uint32x2_t a, uint32x2_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<uint> Or(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// uint64x1_t vorr_u64 (uint64x1_t a, uint64x1_t b)
- // /// A32: VORR Dd, Dn, Dm
- // /// A64: ORR Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<ulong> Or(Vector64<ulong> left, Vector64<ulong> right) { throw new PlatformNotSupportedException(); }
-
/// <summary>
- /// uint8x16_t vorr_u8 (uint8x16_t a, uint8x16_t b)
+ /// uint64x1_t vorr_u64 (uint64x1_t a, uint64x1_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<ulong> Or(Vector64<ulong> left, Vector64<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint8x16_t vorrq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<byte> Or(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// float64x2_t vorr_f64 (float64x2_t a, float64x2_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// float64x2_t vorrq_f64 (float64x2_t a, float64x2_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<double> Or(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int16x8_t vorr_s16 (int16x8_t a, int16x8_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// int16x8_t vorrq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<short> Or(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int32x4_t vorr_s32(int32x4_t a, int32x4_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// int32x4_t vorrq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<int> Or(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int64x2_t vorr_s64 (int64x2_t a, int64x2_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// int64x2_t vorrq_s64 (int64x2_t a, int64x2_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<long> Or(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int8x16_t vorr_s8 (int8x16_t a, int8x16_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// int8x16_t vorrq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<sbyte> Or(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// float32x4_t vorr_f32 (float32x4_t a, float32x4_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// float32x4_t vorrq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<float> Or(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint16x8_t vorr_u16 (uint16x8_t a, uint16x8_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// uint16x8_t vorrq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ushort> Or(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint32x4_t vorr_u32 (uint32x4_t a, uint32x4_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// uint32x4_t vorrq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<uint> Or(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint64x2_t vorr_u64 (uint64x2_t a, uint64x2_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// uint64x2_t vorrq_u64 (uint64x2_t a, uint64x2_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ulong> Or(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint8x8_t vorn_u8 (uint8x8_t a, uint8x8_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<byte> OrNot(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// float64x1_t vorn_f64 (float64x1_t a, float64x1_t b)
- // /// A32: VORN Dd, Dn, Dm
- // /// A64: ORN Vd, Vn, Vm
- // /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
- // /// </summary>
- // public static Vector64<double> OrNot(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// float64x1_t vorn_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VORN Dd, Dn, Dm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<double> OrNot(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// int16x4_t vorn_s16 (int16x4_t a, int16x4_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<short> OrNot(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int32x2_t vorn_s32(int32x2_t a, int32x2_t b)
+ /// int32x2_t vorn_s32 (int32x2_t a, int32x2_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<int> OrNot(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// int64x1_t vorn_s64 (int64x1_t a, int64x1_t b)
- // /// A32: VORN Dd, Dn, Dm
- // /// A64: ORN Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<long> OrNot(Vector64<long> left, Vector64<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int64x1_t vorn_s64 (int64x1_t a, int64x1_t b)
+ /// A32: VORN Dd, Dn, Dm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<long> OrNot(Vector64<long> left, Vector64<long> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// int8x8_t vorn_s8 (int8x8_t a, int8x8_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<sbyte> OrNot(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// float32x2_t vorn_f32 (float32x2_t a, float32x2_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector64<float> OrNot(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint16x4_t vorn_u16 (uint16x4_t a, uint16x4_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<ushort> OrNot(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint32x2_t vorn_u32 (uint32x2_t a, uint32x2_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<uint> OrNot(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// uint64x1_t vorn_u64 (uint64x1_t a, uint64x1_t b)
- // /// A32: VORN Dd, Dn, Dm
- // /// A64: ORN Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<ulong> OrNot(Vector64<ulong> left, Vector64<ulong> right) { throw new PlatformNotSupportedException(); }
-
/// <summary>
- /// uint8x16_t vorn_u8 (uint8x16_t a, uint8x16_t b)
+ /// uint64x1_t vorn_u64 (uint64x1_t a, uint64x1_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<ulong> OrNot(Vector64<ulong> left, Vector64<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint8x16_t vornq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<byte> OrNot(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// float64x2_t vorn_f64 (float64x2_t a, float64x2_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// float64x2_t vornq_f64 (float64x2_t a, float64x2_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<double> OrNot(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int16x8_t vorn_s16 (int16x8_t a, int16x8_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// int16x8_t vornq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<short> OrNot(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int32x4_t vorn_s32(int32x4_t a, int32x4_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// int32x4_t vornq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<int> OrNot(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int64x2_t vorn_s64 (int64x2_t a, int64x2_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// int64x2_t vornq_s64 (int64x2_t a, int64x2_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<long> OrNot(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int8x16_t vorn_s8 (int8x16_t a, int8x16_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// int8x16_t vornq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<sbyte> OrNot(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// float32x4_t vorn_f32 (float32x4_t a, float32x4_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// float32x4_t vornq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<float> OrNot(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint16x8_t vorn_u16 (uint16x8_t a, uint16x8_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// uint16x8_t vornq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ushort> OrNot(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint32x4_t vorn_u32 (uint32x4_t a, uint32x4_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// uint32x4_t vornq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<uint> OrNot(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint64x2_t vorn_u64 (uint64x2_t a, uint64x2_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// uint64x2_t vornq_u64 (uint64x2_t a, uint64x2_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ulong> OrNot(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
public static Vector128<sbyte> PopCount(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
/// <summary>
+ /// float64x1_t vsqrt_f64 (float64x1_t a)
+ /// A32: VSQRT.F64 Dd, Dm
+ /// A64: FSQRT Dd, Dn
+ /// </summary>
+ public static Vector64<double> SqrtScalar(Vector64<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float32_t vsqrts_f32 (float32_t a)
+ /// A32: VSQRT.F32 Sd, Sm
+ /// A64: FSQRT Sd, Sn
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<float> SqrtScalar(Vector64<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
/// uint8x8_t vsub_u8 (uint8x8_t a, uint8x8_t b)
/// A32: VSUB.I8 Dd, Dn, Dm
/// A64: SUB Vd.8B, Vn.8B, Vm.8B
/// <summary>
/// float32x2_t vsub_f32 (float32x2_t a, float32x2_t b)
/// A32: VSUB.F32 Dd, Dn, Dm
- /// A64: FADD Vd.2S, Vn.2S, Vm.2S
+ /// A64: FSUB Vd.2S, Vn.2S, Vm.2S
/// </summary>
public static Vector64<float> Subtract(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// float32x4_t vsubq_f32 (float32x4_t a, float32x4_t b)
/// A32: VSUB.F32 Qd, Qn, Qm
- /// A64: FADD Vd.4S, Vn.4S, Vm.4S
+ /// A64: FSUB Vd.4S, Vn.4S, Vm.4S
/// </summary>
public static Vector128<float> Subtract(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
/// </summary>
public static Vector128<ulong> Subtract(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// float64x1_t vsub_f64 (float64x1_t a, float64x1_t b)
- // /// A32: VSUB.F64 Dd, Dn, Dm
- // /// A64: FADD Dd, Dn, Dm
- // /// </summary>
- // public static Vector64<double> SubtractScalar(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
-
- // /// <summary>
- // /// int64x1_t vsub_s64 (int64x1_t a, int64x1_t b)
- // /// A32: VSUB.I64 Dd, Dn, Dm
- // /// A64: SUB Dd, Dn, Dm
- // /// </summary>
- // public static Vector64<long> SubtractScalar(Vector64<long> left, Vector64<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// float64x1_t vsub_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VSUB.F64 Dd, Dn, Dm
+ /// A64: FSUB Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<double> SubtractScalar(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// uint64x1_t vsub_u64 (uint64x1_t a, uint64x1_t b)
- // /// A32: VSUB.I64 Dd, Dn, Dm
- // /// A64: SUB Dd, Dn, Dm
- // /// </summary>
- // public static Vector64<ulong> SubtractScalar(Vector64<ulong> left, Vector64<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int64x1_t vsub_s64 (int64x1_t a, int64x1_t b)
+ /// A32: VSUB.I64 Dd, Dn, Dm
+ /// A64: SUB Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<long> SubtractScalar(Vector64<long> left, Vector64<long> right) { throw new PlatformNotSupportedException(); }
/// <summary>
+ /// float32_t vsubs_f32 (float32_t a, float32_t b)
/// A32: VSUB.F32 Sd, Sn, Sm
- /// A64:
+ /// A64: FSUB Sd, Sn, Sm
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector64<float> SubtractScalar(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
/// <summary>
+ /// uint64x1_t vsub_u64 (uint64x1_t a, uint64x1_t b)
+ /// A32: VSUB.I64 Dd, Dn, Dm
+ /// A64: SUB Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<ulong> SubtractScalar(Vector64<ulong> left, Vector64<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
/// uint8x8_t veor_u8 (uint8x8_t a, uint8x8_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<byte> Xor(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// float64x1_t veor_f64 (float64x1_t a, float64x1_t b)
- // /// A32: VEOR Dd, Dn, Dm
- // /// A64: EOR Vd, Vn, Vm
- // /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
- // /// </summary>
- // public static Vector64<double> Xor(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// float64x1_t veor_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VEOR Dd, Dn, Dm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<double> Xor(Vector64<double> left, Vector64<double> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// int16x4_t veor_s16 (int16x4_t a, int16x4_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<short> Xor(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int32x2_t veor_s32(int32x2_t a, int32x2_t b)
+ /// int32x2_t veor_s32 (int32x2_t a, int32x2_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<int> Xor(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// int64x1_t veor_s64 (int64x1_t a, int64x1_t b)
- // /// A32: VEOR Dd, Dn, Dm
- // /// A64: EOR Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<long> Xor(Vector64<long> left, Vector64<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int64x1_t veor_s64 (int64x1_t a, int64x1_t b)
+ /// A32: VEOR Dd, Dn, Dm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<long> Xor(Vector64<long> left, Vector64<long> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// int8x8_t veor_s8 (int8x8_t a, int8x8_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<sbyte> Xor(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// float32x2_t veor_f32 (float32x2_t a, float32x2_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector64<float> Xor(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint16x4_t veor_u16 (uint16x4_t a, uint16x4_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<ushort> Xor(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// uint32x2_t veor_u32 (uint32x2_t a, uint32x2_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<uint> Xor(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
- // /// <summary>
- // /// uint64x1_t veor_u64 (uint64x1_t a, uint64x1_t b)
- // /// A32: VEOR Dd, Dn, Dm
- // /// A64: EOR Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<ulong> Xor(Vector64<ulong> left, Vector64<ulong> right) { throw new PlatformNotSupportedException(); }
-
/// <summary>
- /// uint8x16_t veor_u8 (uint8x16_t a, uint8x16_t b)
+ /// uint64x1_t veor_u64 (uint64x1_t a, uint64x1_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<ulong> Xor(Vector64<ulong> left, Vector64<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// uint8x16_t veorq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<byte> Xor(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// float64x2_t veor_f64 (float64x2_t a, float64x2_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// float64x2_t veorq_f64 (float64x2_t a, float64x2_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<double> Xor(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int16x8_t veor_s16 (int16x8_t a, int16x8_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// int16x8_t veorq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<short> Xor(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int32x4_t veor_s32(int32x4_t a, int32x4_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// int32x4_t veorq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<int> Xor(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int64x2_t veor_s64 (int64x2_t a, int64x2_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// int64x2_t veorq_s64 (int64x2_t a, int64x2_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<long> Xor(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// int8x16_t veor_s8 (int8x16_t a, int8x16_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// int8x16_t veorq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<sbyte> Xor(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// float32x4_t veor_f32 (float32x4_t a, float32x4_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// float32x4_t veorq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<float> Xor(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint16x8_t veor_u16 (uint16x8_t a, uint16x8_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// uint16x8_t veorq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ushort> Xor(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint32x4_t veor_u32 (uint32x4_t a, uint32x4_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// uint32x4_t veorq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<uint> Xor(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
/// <summary>
- /// uint64x2_t veor_u64 (uint64x2_t a, uint64x2_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// uint64x2_t veorq_u64 (uint64x2_t a, uint64x2_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ulong> Xor(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
}
public static Vector64<ulong> CompareTestScalar(Vector64<ulong> left, Vector64<ulong> right) => CompareTestScalar(left, right);
/// <summary>
+ /// float32x2_t vdiv_f32 (float32x2_t a, float32x2_t b)
+ /// A64: FDIV Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<float> Divide(Vector64<float> left, Vector64<float> right) => Divide(left, right);
+
+ /// <summary>
+ /// float64x2_t vdivq_f64 (float64x2_t a, float64x2_t b)
+ /// A64: FDIV Vd.2D, Vn.2D, Vm.2D
+ /// </summary>
+ public static Vector128<double> Divide(Vector128<double> left, Vector128<double> right) => Divide(left, right);
+
+ /// <summary>
+ /// float32x4_t vdivq_f32 (float32x4_t a, float32x4_t b)
+ /// A64: FDIV Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<float> Divide(Vector128<float> left, Vector128<float> right) => Divide(left, right);
+
+ /// <summary>
+ /// float64x2_t vmaxq_f64 (float64x2_t a, float64x2_t b)
+ /// A64: FMAX Vd.2D, Vn.2D, Vm.2D
+ /// </summary>
+ public static Vector128<double> Max(Vector128<double> left, Vector128<double> right) => Max(left, right);
+
+ /// <summary>
+ /// float64x1_t vmax_f64 (float64x1_t a, float64x1_t b)
+ /// A64: FMAX Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<double> MaxScalar(Vector64<double> left, Vector64<double> right) => MaxScalar(left, right);
+
+ /// <summary>
+ /// float32_t vmaxs_f32 (float32_t a, float32_t b)
+ /// A64: FMAX Sd, Sn, Sm
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<float> MaxScalar(Vector64<float> left, Vector64<float> right) => MaxScalar(left, right);
+
+ /// <summary>
+ /// float64x2_t vminq_f64 (float64x2_t a, float64x2_t b)
+ /// A64: FMIN Vd.2D, Vn.2D, Vm.2D
+ /// </summary>
+ public static Vector128<double> Min(Vector128<double> left, Vector128<double> right) => Min(left, right);
+
+ /// <summary>
+ /// float64x1_t vmin_f64 (float64x1_t a, float64x1_t b)
+ /// A64: FMIN Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<double> MinScalar(Vector64<double> left, Vector64<double> right) => MinScalar(left, right);
+
+ /// <summary>
+ /// float32_t vmins_f32 (float32_t a, float32_t b)
+ /// A64: FMIN Sd, Sn, Sm
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<float> MinScalar(Vector64<float> left, Vector64<float> right) => MinScalar(left, right);
+
+ /// <summary>
+ /// float64x2_t vmulq_f64 (float64x2_t a, float64x2_t b)
+ /// A64: FMUL Vd.2D, Vn.2D, Vm.2D
+ /// </summary>
+ public static Vector128<double> Multiply(Vector128<double> left, Vector128<double> right) => Multiply(left, right);
+
+ /// <summary>
+ /// float64x2_t vnegq_f64 (float64x2_t a)
+ /// A64: FNEG Vd.2D, Vn.2D
+ /// </summary>
+ public static Vector128<double> Negate(Vector128<double> value) => Negate(value);
+
+ /// <summary>
+ /// int64x2_t vnegq_s64 (int64x2_t a)
+ /// A64: NEG Vd.2D, Vn.2D
+ /// </summary>
+ public static Vector128<long> Negate(Vector128<long> value) => Negate(value);
+
+ /// <summary>
+ /// int64x1_t vneg_s64 (int64x1_t a)
+ /// A64: NEG Dd, Dn
+ /// </summary>
+ public static Vector64<long> NegateScalar(Vector64<long> value) => NegateScalar(value);
+
+ /// <summary>
+ /// float32x2_t vsqrt_f32 (float32x2_t a)
+ /// A64: FSQRT Vd.2S, Vn.2S
+ /// </summary>
+ public static Vector64<float> Sqrt(Vector64<float> value) => Sqrt(value);
+
+ /// <summary>
+ /// float64x2_t vsqrtq_f64 (float64x2_t a)
+ /// A64: FSQRT Vd.2D, Vn.2D
+ /// </summary>
+ public static Vector128<double> Sqrt(Vector128<double> value) => Sqrt(value);
+
+ /// <summary>
+ /// float32x4_t vsqrtq_f32 (float32x4_t a)
+ /// A64: FSQRT Vd.4S, Vn.4S
+ /// </summary>
+ public static Vector128<float> Sqrt(Vector128<float> value) => Sqrt(value);
+
+ /// <summary>
/// float64x2_t vsubq_f64 (float64x2_t a, float64x2_t b)
/// A64: FSUB Vd.2D, Vn.2D, Vm.2D
/// </summary>
- public static Vector128<double> Subtract(Vector128<double> left, Vector128<double> right) => Add(left, right);
+ public static Vector128<double> Subtract(Vector128<double> left, Vector128<double> right) => Subtract(left, right);
/// <summary>
/// uint8x8_t vrbit_u8 (uint8x8_t a)
/// <summary>
/// uint8x8_t vand_u8 (uint8x8_t a, uint8x8_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<byte> And(Vector64<byte> left, Vector64<byte> right) => And(left, right);
- // /// <summary>
- // /// float64x1_t vand_f64 (float64x1_t a, float64x1_t b)
- // /// A32: VAND Dd, Dn, Dm
- // /// A64: AND Vd, Vn, Vm
- // /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
- // /// </summary>
- // public static Vector64<double> And(Vector64<double> left, Vector64<double> right) => And(left, right);
+ /// <summary>
+ /// float64x1_t vand_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VAND Dd, Dn, Dm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<double> And(Vector64<double> left, Vector64<double> right) => And(left, right);
/// <summary>
/// int16x4_t vand_s16 (int16x4_t a, int16x4_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<short> And(Vector64<short> left, Vector64<short> right) => And(left, right);
/// <summary>
- /// int32x2_t vand_s32(int32x2_t a, int32x2_t b)
+ /// int32x2_t vand_s32 (int32x2_t a, int32x2_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<int> And(Vector64<int> left, Vector64<int> right) => And(left, right);
- // /// <summary>
- // /// int64x1_t vand_s64 (int64x1_t a, int64x1_t b)
- // /// A32: VAND Dd, Dn, Dm
- // /// A64: AND Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<long> And(Vector64<long> left, Vector64<long> right) => And(left, right);
+ /// <summary>
+ /// int64x1_t vand_s64 (int64x1_t a, int64x1_t b)
+ /// A32: VAND Dd, Dn, Dm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<long> And(Vector64<long> left, Vector64<long> right) => And(left, right);
/// <summary>
/// int8x8_t vand_s8 (int8x8_t a, int8x8_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<sbyte> And(Vector64<sbyte> left, Vector64<sbyte> right) => And(left, right);
/// <summary>
/// float32x2_t vand_f32 (float32x2_t a, float32x2_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector64<float> And(Vector64<float> left, Vector64<float> right) => And(left, right);
/// <summary>
/// uint16x4_t vand_u16 (uint16x4_t a, uint16x4_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<ushort> And(Vector64<ushort> left, Vector64<ushort> right) => And(left, right);
/// <summary>
/// uint32x2_t vand_u32 (uint32x2_t a, uint32x2_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<uint> And(Vector64<uint> left, Vector64<uint> right) => And(left, right);
- // /// <summary>
- // /// uint64x1_t vand_u64 (uint64x1_t a, uint64x1_t b)
- // /// A32: VAND Dd, Dn, Dm
- // /// A64: AND Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<ulong> And(Vector64<ulong> left, Vector64<ulong> right) => And(left, right);
-
/// <summary>
- /// uint8x16_t vand_u8 (uint8x16_t a, uint8x16_t b)
+ /// uint64x1_t vand_u64 (uint64x1_t a, uint64x1_t b)
/// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// A64: AND Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<ulong> And(Vector64<ulong> left, Vector64<ulong> right) => And(left, right);
+
+ /// <summary>
+ /// uint8x16_t vandq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<byte> And(Vector128<byte> left, Vector128<byte> right) => And(left, right);
/// <summary>
- /// float64x2_t vand_f64 (float64x2_t a, float64x2_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// float64x2_t vandq_f64 (float64x2_t a, float64x2_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<double> And(Vector128<double> left, Vector128<double> right) => And(left, right);
/// <summary>
- /// int16x8_t vand_s16 (int16x8_t a, int16x8_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// int16x8_t vandq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<short> And(Vector128<short> left, Vector128<short> right) => And(left, right);
/// <summary>
- /// int32x4_t vand_s32(int32x4_t a, int32x4_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// int32x4_t vandq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<int> And(Vector128<int> left, Vector128<int> right) => And(left, right);
/// <summary>
- /// int64x2_t vand_s64 (int64x2_t a, int64x2_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// int64x2_t vandq_s64 (int64x2_t a, int64x2_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<long> And(Vector128<long> left, Vector128<long> right) => And(left, right);
/// <summary>
- /// int8x16_t vand_s8 (int8x16_t a, int8x16_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// int8x16_t vandq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<sbyte> And(Vector128<sbyte> left, Vector128<sbyte> right) => And(left, right);
/// <summary>
- /// float32x4_t vand_f32 (float32x4_t a, float32x4_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// float32x4_t vandq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<float> And(Vector128<float> left, Vector128<float> right) => And(left, right);
/// <summary>
- /// uint16x8_t vand_u16 (uint16x8_t a, uint16x8_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// uint16x8_t vandq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ushort> And(Vector128<ushort> left, Vector128<ushort> right) => And(left, right);
/// <summary>
- /// uint32x4_t vand_u32 (uint32x4_t a, uint32x4_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// uint32x4_t vandq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<uint> And(Vector128<uint> left, Vector128<uint> right) => And(left, right);
/// <summary>
- /// uint64x2_t vand_u64 (uint64x2_t a, uint64x2_t b)
- /// A32: VAND Dd, Dn, Dm
- /// A64: AND Vd, Vn, Vm
+ /// uint64x2_t vandq_u64 (uint64x2_t a, uint64x2_t b)
+ /// A32: VAND Qd, Qn, Qm
+ /// A64: AND Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ulong> And(Vector128<ulong> left, Vector128<ulong> right) => And(left, right);
/// <summary>
/// uint8x8_t vbic_u8 (uint8x8_t a, uint8x8_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector64<byte> AndNot(Vector64<byte> left, Vector64<byte> right) => AndNot(left, right);
+ public static Vector64<byte> BitwiseClear(Vector64<byte> value, Vector64<byte> mask) => BitwiseClear(value, mask);
- // /// <summary>
- // /// float64x1_t vbic_f64 (float64x1_t a, float64x1_t b)
- // /// A32: VBIC Dd, Dn, Dm
- // /// A64: BIC Vd, Vn, Vm
- // /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
- // /// </summary>
- // public static Vector64<double> AndNot(Vector64<double> left, Vector64<double> right) => AndNot(left, right);
+ /// <summary>
+ /// float64x1_t vbic_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VBIC Dd, Dn, Dm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<double> BitwiseClear(Vector64<double> value, Vector64<double> mask) => BitwiseClear(value, mask);
/// <summary>
/// int16x4_t vbic_s16 (int16x4_t a, int16x4_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector64<short> AndNot(Vector64<short> left, Vector64<short> right) => AndNot(left, right);
+ public static Vector64<short> BitwiseClear(Vector64<short> value, Vector64<short> mask) => BitwiseClear(value, mask);
/// <summary>
- /// int32x2_t vbic_s32(int32x2_t a, int32x2_t b)
+ /// int32x2_t vbic_s32 (int32x2_t a, int32x2_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector64<int> AndNot(Vector64<int> left, Vector64<int> right) => AndNot(left, right);
+ public static Vector64<int> BitwiseClear(Vector64<int> value, Vector64<int> mask) => BitwiseClear(value, mask);
- // /// <summary>
- // /// int64x1_t vbic_s64 (int64x1_t a, int64x1_t b)
- // /// A32: VBIC Dd, Dn, Dm
- // /// A64: BIC Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<long> AndNot(Vector64<long> left, Vector64<long> right) => AndNot(left, right);
+ /// <summary>
+ /// int64x1_t vbic_s64 (int64x1_t a, int64x1_t b)
+ /// A32: VBIC Dd, Dn, Dm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<long> BitwiseClear(Vector64<long> value, Vector64<long> mask) => BitwiseClear(value, mask);
/// <summary>
/// int8x8_t vbic_s8 (int8x8_t a, int8x8_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector64<sbyte> AndNot(Vector64<sbyte> left, Vector64<sbyte> right) => AndNot(left, right);
+ public static Vector64<sbyte> BitwiseClear(Vector64<sbyte> value, Vector64<sbyte> mask) => BitwiseClear(value, mask);
/// <summary>
/// float32x2_t vbic_f32 (float32x2_t a, float32x2_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
- public static Vector64<float> AndNot(Vector64<float> left, Vector64<float> right) => AndNot(left, right);
+ public static Vector64<float> BitwiseClear(Vector64<float> value, Vector64<float> mask) => BitwiseClear(value, mask);
/// <summary>
/// uint16x4_t vbic_u16 (uint16x4_t a, uint16x4_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector64<ushort> AndNot(Vector64<ushort> left, Vector64<ushort> right) => AndNot(left, right);
+ public static Vector64<ushort> BitwiseClear(Vector64<ushort> value, Vector64<ushort> mask) => BitwiseClear(value, mask);
/// <summary>
/// uint32x2_t vbic_u32 (uint32x2_t a, uint32x2_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector64<uint> AndNot(Vector64<uint> left, Vector64<uint> right) => AndNot(left, right);
-
- // /// <summary>
- // /// uint64x1_t vbic_u64 (uint64x1_t a, uint64x1_t b)
- // /// A32: VBIC Dd, Dn, Dm
- // /// A64: BIC Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<ulong> AndNot(Vector64<ulong> left, Vector64<ulong> right) => AndNot(left, right);
+ public static Vector64<uint> BitwiseClear(Vector64<uint> value, Vector64<uint> mask) => BitwiseClear(value, mask);
/// <summary>
- /// uint8x16_t vbic_u8 (uint8x16_t a, uint8x16_t b)
+ /// uint64x1_t vbic_u64 (uint64x1_t a, uint64x1_t b)
/// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// A64: BIC Vd.8B, Vn.8B, Vm.8B
/// </summary>
- public static Vector128<byte> AndNot(Vector128<byte> left, Vector128<byte> right) => AndNot(left, right);
+ public static Vector64<ulong> BitwiseClear(Vector64<ulong> value, Vector64<ulong> mask) => BitwiseClear(value, mask);
/// <summary>
- /// float64x2_t vbic_f64 (float64x2_t a, float64x2_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// uint8x16_t vbicq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<byte> BitwiseClear(Vector128<byte> value, Vector128<byte> mask) => BitwiseClear(value, mask);
+
+ /// <summary>
+ /// float64x2_t vbicq_f64 (float64x2_t a, float64x2_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
- public static Vector128<double> AndNot(Vector128<double> left, Vector128<double> right) => AndNot(left, right);
+ public static Vector128<double> BitwiseClear(Vector128<double> value, Vector128<double> mask) => BitwiseClear(value, mask);
/// <summary>
- /// int16x8_t vbic_s16 (int16x8_t a, int16x8_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// int16x8_t vbicq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<short> AndNot(Vector128<short> left, Vector128<short> right) => AndNot(left, right);
+ public static Vector128<short> BitwiseClear(Vector128<short> value, Vector128<short> mask) => BitwiseClear(value, mask);
/// <summary>
- /// int32x4_t vbic_s32(int32x4_t a, int32x4_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// int32x4_t vbicq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<int> AndNot(Vector128<int> left, Vector128<int> right) => AndNot(left, right);
+ public static Vector128<int> BitwiseClear(Vector128<int> value, Vector128<int> mask) => BitwiseClear(value, mask);
/// <summary>
- /// int64x2_t vbic_s64 (int64x2_t a, int64x2_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// int64x2_t vbicq_s64 (int64x2_t a, int64x2_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<long> AndNot(Vector128<long> left, Vector128<long> right) => AndNot(left, right);
+ public static Vector128<long> BitwiseClear(Vector128<long> value, Vector128<long> mask) => BitwiseClear(value, mask);
/// <summary>
- /// int8x16_t vbic_s8 (int8x16_t a, int8x16_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// int8x16_t vbicq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<sbyte> AndNot(Vector128<sbyte> left, Vector128<sbyte> right) => AndNot(left, right);
+ public static Vector128<sbyte> BitwiseClear(Vector128<sbyte> value, Vector128<sbyte> mask) => BitwiseClear(value, mask);
/// <summary>
- /// float32x4_t vbic_f32 (float32x4_t a, float32x4_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// float32x4_t vbicq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
- public static Vector128<float> AndNot(Vector128<float> left, Vector128<float> right) => AndNot(left, right);
+ public static Vector128<float> BitwiseClear(Vector128<float> value, Vector128<float> mask) => BitwiseClear(value, mask);
/// <summary>
- /// uint16x8_t vbic_u16 (uint16x8_t a, uint16x8_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// uint16x8_t vbicq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<ushort> AndNot(Vector128<ushort> left, Vector128<ushort> right) => AndNot(left, right);
+ public static Vector128<ushort> BitwiseClear(Vector128<ushort> value, Vector128<ushort> mask) => BitwiseClear(value, mask);
/// <summary>
- /// uint32x4_t vbic_u32 (uint32x4_t a, uint32x4_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// uint32x4_t vbicq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<uint> AndNot(Vector128<uint> left, Vector128<uint> right) => AndNot(left, right);
+ public static Vector128<uint> BitwiseClear(Vector128<uint> value, Vector128<uint> mask) => BitwiseClear(value, mask);
/// <summary>
- /// uint64x2_t vbic_u64 (uint64x2_t a, uint64x2_t b)
- /// A32: VBIC Dd, Dn, Dm
- /// A64: BIC Vd, Vn, Vm
+ /// uint64x2_t vbicq_u64 (uint64x2_t a, uint64x2_t b)
+ /// A32: VBIC Qd, Qn, Qm
+ /// A64: BIC Vd.16B, Vn.16B, Vm.16B
/// </summary>
- public static Vector128<ulong> AndNot(Vector128<ulong> left, Vector128<ulong> right) => AndNot(left, right);
+ public static Vector128<ulong> BitwiseClear(Vector128<ulong> value, Vector128<ulong> mask) => BitwiseClear(value, mask);
/// <summary>
/// uint8x8_t vbsl_u8 (uint8x8_t a, uint8x8_t b, uint8x8_t c)
public static Vector128<uint> CompareTest(Vector128<uint> left, Vector128<uint> right) => CompareTest(left, right);
/// <summary>
+ /// float64x1_t vdiv_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VDIV.F64 Dd, Dn, Dm
+ /// A64: FDIV Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<double> DivideScalar(Vector64<double> left, Vector64<double> right) => DivideScalar(left, right);
+
+ /// <summary>
+ /// float32_t vdivs_f32 (float32_t a, float32_t b)
+ /// A32: VDIV.F32 Sd, Sn, Sm
+ /// A64: FDIV Sd, Sn, Sm
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<float> DivideScalar(Vector64<float> left, Vector64<float> right) => DivideScalar(left, right);
+
+ /// <summary>
/// int16x4_t vcls_s16 (int16x4_t a)
/// A32: VCLS.S16 Dd, Dm
/// A64: CLS Vd.4H, Vn.4H
public static unsafe Vector128<ulong> LoadVector128(ulong* address) => LoadVector128(address);
/// <summary>
+ /// uint8x8_t vmax_u8 (uint8x8_t a, uint8x8_t b)
+ /// A32: VMAX.U8 Dd, Dn, Dm
+ /// A64: UMAX Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<byte> Max(Vector64<byte> left, Vector64<byte> right) => Max(left, right);
+
+ /// <summary>
+ /// int16x4_t vmax_s16 (int16x4_t a, int16x4_t b)
+ /// A32: VMAX.S16 Dd, Dn, Dm
+ /// A64: SMAX Vd.4H, Vn.4H, Vm.4H
+ /// </summary>
+ public static Vector64<short> Max(Vector64<short> left, Vector64<short> right) => Max(left, right);
+
+ /// <summary>
+ /// int32x2_t vmax_s32 (int32x2_t a, int32x2_t b)
+ /// A32: VMAX.S32 Dd, Dn, Dm
+ /// A64: SMAX Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<int> Max(Vector64<int> left, Vector64<int> right) => Max(left, right);
+
+ /// <summary>
+ /// int8x8_t vmax_s8 (int8x8_t a, int8x8_t b)
+ /// A32: VMAX.S8 Dd, Dn, Dm
+ /// A64: SMAX Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<sbyte> Max(Vector64<sbyte> left, Vector64<sbyte> right) => Max(left, right);
+
+ /// <summary>
+ /// float32x2_t vmax_f32 (float32x2_t a, float32x2_t b)
+ /// A32: VMAX.F32 Dd, Dn, Dm
+ /// A64: FMAX Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<float> Max(Vector64<float> left, Vector64<float> right) => Max(left, right);
+
+ /// <summary>
+ /// uint16x4_t vmax_u16 (uint16x4_t a, uint16x4_t b)
+ /// A32: VMAX.U16 Dd, Dn, Dm
+ /// A64: UMAX Vd.4H, Vn.4H, Vm.4H
+ /// </summary>
+ public static Vector64<ushort> Max(Vector64<ushort> left, Vector64<ushort> right) => Max(left, right);
+
+ /// <summary>
+ /// uint32x2_t vmax_u32 (uint32x2_t a, uint32x2_t b)
+ /// A32: VMAX.U32 Dd, Dn, Dm
+ /// A64: UMAX Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<uint> Max(Vector64<uint> left, Vector64<uint> right) => Max(left, right);
+
+ /// <summary>
+ /// uint8x16_t vmaxq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VMAX.U8 Qd, Qn, Qm
+ /// A64: UMAX Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<byte> Max(Vector128<byte> left, Vector128<byte> right) => Max(left, right);
+
+ /// <summary>
+ /// int16x8_t vmaxq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VMAX.S16 Qd, Qn, Qm
+ /// A64: SMAX Vd.8H, Vn.8H, Vm.8H
+ /// </summary>
+ public static Vector128<short> Max(Vector128<short> left, Vector128<short> right) => Max(left, right);
+
+ /// <summary>
+ /// int32x4_t vmaxq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VMAX.S32 Qd, Qn, Qm
+ /// A64: SMAX Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<int> Max(Vector128<int> left, Vector128<int> right) => Max(left, right);
+
+ /// <summary>
+ /// int8x16_t vmaxq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VMAX.S8 Qd, Qn, Qm
+ /// A64: SMAX Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<sbyte> Max(Vector128<sbyte> left, Vector128<sbyte> right) => Max(left, right);
+
+ /// <summary>
+ /// float32x4_t vmaxq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VMAX.F32 Qd, Qn, Qm
+ /// A64: FMAX Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<float> Max(Vector128<float> left, Vector128<float> right) => Max(left, right);
+
+ /// <summary>
+ /// uint16x8_t vmaxq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VMAX.U16 Qd, Qn, Qm
+ /// A64: UMAX Vd.8H, Vn.8H, Vm.8H
+ /// </summary>
+ public static Vector128<ushort> Max(Vector128<ushort> left, Vector128<ushort> right) => Max(left, right);
+
+ /// <summary>
+ /// uint32x4_t vmaxq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VMAX.U32 Qd, Qn, Qm
+ /// A64: UMAX Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<uint> Max(Vector128<uint> left, Vector128<uint> right) => Max(left, right);
+
+ /// <summary>
+ /// uint8x8_t vmin_u8 (uint8x8_t a, uint8x8_t b)
+ /// A32: VMIN.U8 Dd, Dn, Dm
+ /// A64: UMIN Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<byte> Min(Vector64<byte> left, Vector64<byte> right) => Min(left, right);
+
+ /// <summary>
+ /// int16x4_t vmin_s16 (int16x4_t a, int16x4_t b)
+ /// A32: VMIN.S16 Dd, Dn, Dm
+ /// A64: SMIN Vd.4H, Vn.4H, Vm.4H
+ /// </summary>
+ public static Vector64<short> Min(Vector64<short> left, Vector64<short> right) => Min(left, right);
+
+ /// <summary>
+ /// int32x2_t vmin_s32 (int32x2_t a, int32x2_t b)
+ /// A32: VMIN.S32 Dd, Dn, Dm
+ /// A64: SMIN Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<int> Min(Vector64<int> left, Vector64<int> right) => Min(left, right);
+
+ /// <summary>
+ /// int8x8_t vmin_s8 (int8x8_t a, int8x8_t b)
+ /// A32: VMIN.S8 Dd, Dn, Dm
+ /// A64: SMIN Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<sbyte> Min(Vector64<sbyte> left, Vector64<sbyte> right) => Min(left, right);
+
+ /// <summary>
+ /// float32x2_t vmin_f32 (float32x2_t a, float32x2_t b)
+ /// A32: VMIN.F32 Dd, Dn, Dm
+ /// A64: FMIN Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<float> Min(Vector64<float> left, Vector64<float> right) => Min(left, right);
+
+ /// <summary>
+ /// uint16x4_t vmin_u16 (uint16x4_t a, uint16x4_t b)
+ /// A32: VMIN.U16 Dd, Dn, Dm
+ /// A64: UMIN Vd.4H, Vn.4H, Vm.4H
+ /// </summary>
+ public static Vector64<ushort> Min(Vector64<ushort> left, Vector64<ushort> right) => Min(left, right);
+
+ /// <summary>
+ /// uint32x2_t vmin_u32 (uint32x2_t a, uint32x2_t b)
+ /// A32: VMIN.U32 Dd, Dn, Dm
+ /// A64: UMIN Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<uint> Min(Vector64<uint> left, Vector64<uint> right) => Min(left, right);
+
+ /// <summary>
+ /// uint8x16_t vminq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VMIN.U8 Qd, Qn, Qm
+ /// A64: UMIN Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<byte> Min(Vector128<byte> left, Vector128<byte> right) => Min(left, right);
+
+ /// <summary>
+ /// int16x8_t vminq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VMIN.S16 Qd, Qn, Qm
+ /// A64: SMIN Vd.8H, Vn.8H, Vm.8H
+ /// </summary>
+ public static Vector128<short> Min(Vector128<short> left, Vector128<short> right) => Min(left, right);
+
+ /// <summary>
+ /// int32x4_t vminq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VMIN.S32 Qd, Qn, Qm
+ /// A64: SMIN Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<int> Min(Vector128<int> left, Vector128<int> right) => Min(left, right);
+
+ /// <summary>
+ /// int8x16_t vminq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VMIN.S8 Qd, Qn, Qm
+ /// A64: SMIN Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<sbyte> Min(Vector128<sbyte> left, Vector128<sbyte> right) => Min(left, right);
+
+ /// <summary>
+ /// float32x4_t vminq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VMIN.F32 Qd, Qn, Qm
+ /// A64: FMIN Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<float> Min(Vector128<float> left, Vector128<float> right) => Min(left, right);
+
+ /// <summary>
+ /// uint16x8_t vminq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VMIN.U16 Qd, Qn, Qm
+ /// A64: UMIN Vd.8H, Vn.8H, Vm.8H
+ /// </summary>
+ public static Vector128<ushort> Min(Vector128<ushort> left, Vector128<ushort> right) => Min(left, right);
+
+ /// <summary>
+ /// uint32x4_t vminq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VMIN.U32 Qd, Qn, Qm
+ /// A64: UMIN Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<uint> Min(Vector128<uint> left, Vector128<uint> right) => Min(left, right);
+
+ /// <summary>
+ /// uint8x8_t vmul_u8 (uint8x8_t a, uint8x8_t b)
+ /// A32: VMUL.I8 Dd, Dn, Dm
+ /// A64: MUL Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<byte> Multiply(Vector64<byte> left, Vector64<byte> right) => Multiply(left, right);
+
+ /// <summary>
+ /// int16x4_t vmul_s16 (int16x4_t a, int16x4_t b)
+ /// A32: VMUL.I16 Dd, Dn, Dm
+ /// A64: MUL Vd.4H, Vn.4H, Vm.4H
+ /// </summary>
+ public static Vector64<short> Multiply(Vector64<short> left, Vector64<short> right) => Multiply(left, right);
+
+ /// <summary>
+ /// int32x2_t vmul_s32 (int32x2_t a, int32x2_t b)
+ /// A32: VMUL.I32 Dd, Dn, Dm
+ /// A64: MUL Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<int> Multiply(Vector64<int> left, Vector64<int> right) => Multiply(left, right);
+
+ /// <summary>
+ /// int8x8_t vmul_s8 (int8x8_t a, int8x8_t b)
+ /// A32: VMUL.I8 Dd, Dn, Dm
+ /// A64: MUL Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<sbyte> Multiply(Vector64<sbyte> left, Vector64<sbyte> right) => Multiply(left, right);
+
+ /// <summary>
+ /// float32x2_t vmul_f32 (float32x2_t a, float32x2_t b)
+ /// A32: VMUL.F32 Dd, Dn, Dm
+ /// A64: FMUL Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<float> Multiply(Vector64<float> left, Vector64<float> right) => Multiply(left, right);
+
+ /// <summary>
+ /// uint16x4_t vmul_u16 (uint16x4_t a, uint16x4_t b)
+ /// A32: VMUL.I16 Dd, Dn, Dm
+ /// A64: MUL Vd.4H, Vn.4H, Vm.4H
+ /// </summary>
+ public static Vector64<ushort> Multiply(Vector64<ushort> left, Vector64<ushort> right) => Multiply(left, right);
+
+ /// <summary>
+ /// uint32x2_t vmul_u32 (uint32x2_t a, uint32x2_t b)
+ /// A32: VMUL.I32 Dd, Dn, Dm
+ /// A64: MUL Vd.2S, Vn.2S, Vm.2S
+ /// </summary>
+ public static Vector64<uint> Multiply(Vector64<uint> left, Vector64<uint> right) => Multiply(left, right);
+
+ /// <summary>
+ /// uint8x16_t vmulq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VMUL.I8 Qd, Qn, Qm
+ /// A64: MUL Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<byte> Multiply(Vector128<byte> left, Vector128<byte> right) => Multiply(left, right);
+
+ /// <summary>
+ /// int16x8_t vmulq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VMUL.I16 Qd, Qn, Qm
+ /// A64: MUL Vd.8H, Vn.8H, Vm.8H
+ /// </summary>
+ public static Vector128<short> Multiply(Vector128<short> left, Vector128<short> right) => Multiply(left, right);
+
+ /// <summary>
+ /// int32x4_t vmulq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VMUL.I32 Qd, Qn, Qm
+ /// A64: MUL Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<int> Multiply(Vector128<int> left, Vector128<int> right) => Multiply(left, right);
+
+ /// <summary>
+ /// int8x16_t vmulq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VMUL.I8 Qd, Qn, Qm
+ /// A64: MUL Vd.16B, Vn.16B, Vm.16B
+ /// </summary>
+ public static Vector128<sbyte> Multiply(Vector128<sbyte> left, Vector128<sbyte> right) => Multiply(left, right);
+
+ /// <summary>
+ /// float32x4_t vmulq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VMUL.F32 Qd, Qn, Qm
+ /// A64: FMUL Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<float> Multiply(Vector128<float> left, Vector128<float> right) => Multiply(left, right);
+
+ /// <summary>
+ /// uint16x8_t vmulq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VMUL.I16 Qd, Qn, Qm
+ /// A64: MUL Vd.8H, Vn.8H, Vm.8H
+ /// </summary>
+ public static Vector128<ushort> Multiply(Vector128<ushort> left, Vector128<ushort> right) => Multiply(left, right);
+
+ /// <summary>
+ /// uint32x4_t vmulq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VMUL.I32 Qd, Qn, Qm
+ /// A64: MUL Vd.4S, Vn.4S, Vm.4S
+ /// </summary>
+ public static Vector128<uint> Multiply(Vector128<uint> left, Vector128<uint> right) => Multiply(left, right);
+
+ /// <summary>
+ /// float64x1_t vmul_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VMUL.F64 Dd, Dn, Dm
+ /// A64: FMUL Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<double> MultiplyScalar(Vector64<double> left, Vector64<double> right) => MultiplyScalar(left, right);
+
+ /// <summary>
+ /// float32_t vmuls_f32 (float32_t a, float32_t b)
+ /// A32: VMUL.F32 Sd, Sn, Sm
+ /// A64: FMUL Sd, Sn, Sm
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<float> MultiplyScalar(Vector64<float> left, Vector64<float> right) => MultiplyScalar(left, right);
+
+ /// <summary>
+ /// int16x4_t vneg_s16 (int16x4_t a)
+ /// A32: VNEG.S16 Dd, Dm
+ /// A64: NEG Vd.4H, Vn.4H
+ /// </summary>
+ public static Vector64<short> Negate(Vector64<short> value) => Negate(value);
+
+ /// <summary>
+ /// int32x2_t vneg_s32 (int32x2_t a)
+ /// A32: VNEG.S32 Dd, Dm
+ /// A64: NEG Vd.2S, Vn.2S
+ /// </summary>
+ public static Vector64<int> Negate(Vector64<int> value) => Negate(value);
+
+ /// <summary>
+ /// int8x8_t vneg_s8 (int8x8_t a)
+ /// A32: VNEG.S8 Dd, Dm
+ /// A64: NEG Vd.8B, Vn.8B
+ /// </summary>
+ public static Vector64<sbyte> Negate(Vector64<sbyte> value) => Negate(value);
+
+ /// <summary>
+ /// float32x2_t vneg_f32 (float32x2_t a)
+ /// A32: VNEG.F32 Dd, Dm
+ /// A64: FNEG Vd.2S, Vn.2S
+ /// </summary>
+ public static Vector64<float> Negate(Vector64<float> value) => Negate(value);
+
+ /// <summary>
+ /// int16x8_t vnegq_s16 (int16x8_t a)
+ /// A32: VNEG.S16 Qd, Qm
+ /// A64: NEG Vd.8H, Vn.8H
+ /// </summary>
+ public static Vector128<short> Negate(Vector128<short> value) => Negate(value);
+
+ /// <summary>
+ /// int32x4_t vnegq_s32 (int32x4_t a)
+ /// A32: VNEG.S32 Qd, Qm
+ /// A64: NEG Vd.4S, Vn.4S
+ /// </summary>
+ public static Vector128<int> Negate(Vector128<int> value) => Negate(value);
+
+ /// <summary>
+ /// int8x16_t vnegq_s8 (int8x16_t a)
+ /// A32: VNEG.S8 Qd, Qm
+ /// A64: NEG Vd.16B, Vn.16B
+ /// </summary>
+ public static Vector128<sbyte> Negate(Vector128<sbyte> value) => Negate(value);
+
+ /// <summary>
+ /// float32x4_t vnegq_f32 (float32x4_t a)
+ /// A32: VNEG.F32 Qd, Qm
+ /// A64: FNEG Vd.4S, Vn.4S
+ /// </summary>
+ public static Vector128<float> Negate(Vector128<float> value) => Negate(value);
+
+ /// <summary>
+ /// float64x1_t vneg_f64 (float64x1_t a)
+ /// A32: VNEG.F64 Dd, Dm
+ /// A64: FNEG Dd, Dn
+ /// </summary>
+ public static Vector64<double> NegateScalar(Vector64<double> value) => NegateScalar(value);
+
+ /// <summary>
+ /// float32_t vnegs_f32 (float32_t a)
+ /// A32: VNEG.F32 Sd, Sm
+ /// A64: FNEG Sd, Sn
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<float> NegateScalar(Vector64<float> value) => NegateScalar(value);
+
+ /// <summary>
/// uint8x8_t vmvn_u8 (uint8x8_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// </summary>
public static Vector64<byte> Not(Vector64<byte> value) => Not(value);
- // /// <summary>
- // /// float64x1_t vmvn_f64 (float64x1_t a)
- // /// A32: VMVN Dd, Dn, Dm
- // /// A64: MVN Vd, Vn, Vm
- // /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
- // /// </summary>
- // public static Vector64<double> Not(Vector64<double> value) => Not(value);
+ /// <summary>
+ /// float64x1_t vmvn_f64 (float64x1_t a)
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<double> Not(Vector64<double> value) => Not(value);
/// <summary>
/// int16x4_t vmvn_s16 (int16x4_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// </summary>
public static Vector64<short> Not(Vector64<short> value) => Not(value);
/// <summary>
- /// int32x2_t vmvn_s32(int32x2_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// int32x2_t vmvn_s32 (int32x2_t a)
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// </summary>
public static Vector64<int> Not(Vector64<int> value) => Not(value);
- // /// <summary>
- // /// int64x1_t vmvn_s64 (int64x1_t a)
- // /// A32: VMVN Dd, Dn, Dm
- // /// A64: MVN Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<long> Not(Vector64<long> value) => Not(value);
+ /// <summary>
+ /// int64x1_t vmvn_s64 (int64x1_t a)
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
+ /// </summary>
+ public static Vector64<long> Not(Vector64<long> value) => Not(value);
/// <summary>
/// int8x8_t vmvn_s8 (int8x8_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// </summary>
public static Vector64<sbyte> Not(Vector64<sbyte> value) => Not(value);
/// <summary>
/// float32x2_t vmvn_f32 (float32x2_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector64<float> Not(Vector64<float> value) => Not(value);
/// <summary>
/// uint16x4_t vmvn_u16 (uint16x4_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// </summary>
public static Vector64<ushort> Not(Vector64<ushort> value) => Not(value);
/// <summary>
/// uint32x2_t vmvn_u32 (uint32x2_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
/// </summary>
public static Vector64<uint> Not(Vector64<uint> value) => Not(value);
- // /// <summary>
- // /// uint64x1_t vmvn_u64 (uint64x1_t a)
- // /// A32: VMVN Dd, Dn, Dm
- // /// A64: MVN Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<ulong> Not(Vector64<ulong> value) => Not(value);
+ /// <summary>
+ /// uint64x1_t vmvn_u64 (uint64x1_t a)
+ /// A32: VMVN Dd, Dm
+ /// A64: MVN Vd.8B, Vn.8B
+ /// </summary>
+ public static Vector64<ulong> Not(Vector64<ulong> value) => Not(value);
/// <summary>
- /// uint8x16_t vmvn_u8 (uint8x16_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// uint8x16_t vmvnq_u8 (uint8x16_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<byte> Not(Vector128<byte> value) => Not(value);
/// <summary>
- /// float64x2_t vmvn_f64 (float64x2_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// float64x2_t vmvnq_f64 (float64x2_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<double> Not(Vector128<double> value) => Not(value);
/// <summary>
- /// int16x8_t vmvn_s16 (int16x8_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// int16x8_t vmvnq_s16 (int16x8_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<short> Not(Vector128<short> value) => Not(value);
/// <summary>
- /// int32x4_t vmvn_s32(int32x4_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// int32x4_t vmvnq_s32 (int32x4_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<int> Not(Vector128<int> value) => Not(value);
/// <summary>
- /// int64x2_t vmvn_s64 (int64x2_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// int64x2_t vmvnq_s64 (int64x2_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<long> Not(Vector128<long> value) => Not(value);
/// <summary>
- /// int8x16_t vmvn_s8 (int8x16_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// int8x16_t vmvnq_s8 (int8x16_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<sbyte> Not(Vector128<sbyte> value) => Not(value);
/// <summary>
- /// float32x4_t vmvn_f32 (float32x4_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// float32x4_t vmvnq_f32 (float32x4_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<float> Not(Vector128<float> value) => Not(value);
/// <summary>
- /// uint16x8_t vmvn_u16 (uint16x8_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// uint16x8_t vmvnq_u16 (uint16x8_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<ushort> Not(Vector128<ushort> value) => Not(value);
/// <summary>
- /// uint32x4_t vmvn_u32 (uint32x4_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// uint32x4_t vmvnq_u32 (uint32x4_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<uint> Not(Vector128<uint> value) => Not(value);
/// <summary>
- /// uint64x2_t vmvn_u64 (uint64x2_t a)
- /// A32: VMVN Dd, Dn, Dm
- /// A64: MVN Vd, Vn, Vm
+ /// uint64x2_t vmvnq_u64 (uint64x2_t a)
+ /// A32: VMVN Qd, Qm
+ /// A64: MVN Vd.16B, Vn.16B
/// </summary>
public static Vector128<ulong> Not(Vector128<ulong> value) => Not(value);
/// <summary>
/// uint8x8_t vorr_u8 (uint8x8_t a, uint8x8_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<byte> Or(Vector64<byte> left, Vector64<byte> right) => Or(left, right);
- // /// <summary>
- // /// float64x1_t vorr_f64 (float64x1_t a, float64x1_t b)
- // /// A32: VORR Dd, Dn, Dm
- // /// A64: ORR Vd, Vn, Vm
- // /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
- // /// </summary>
- // public static Vector64<double> Or(Vector64<double> left, Vector64<double> right) => Or(left, right);
+ /// <summary>
+ /// float64x1_t vorr_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VORR Dd, Dn, Dm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<double> Or(Vector64<double> left, Vector64<double> right) => Or(left, right);
/// <summary>
/// int16x4_t vorr_s16 (int16x4_t a, int16x4_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<short> Or(Vector64<short> left, Vector64<short> right) => Or(left, right);
/// <summary>
- /// int32x2_t vorr_s32(int32x2_t a, int32x2_t b)
+ /// int32x2_t vorr_s32 (int32x2_t a, int32x2_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<int> Or(Vector64<int> left, Vector64<int> right) => Or(left, right);
- // /// <summary>
- // /// int64x1_t vorr_s64 (int64x1_t a, int64x1_t b)
- // /// A32: VORR Dd, Dn, Dm
- // /// A64: ORR Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<long> Or(Vector64<long> left, Vector64<long> right) => Or(left, right);
+ /// <summary>
+ /// int64x1_t vorr_s64 (int64x1_t a, int64x1_t b)
+ /// A32: VORR Dd, Dn, Dm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<long> Or(Vector64<long> left, Vector64<long> right) => Or(left, right);
/// <summary>
/// int8x8_t vorr_s8 (int8x8_t a, int8x8_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<sbyte> Or(Vector64<sbyte> left, Vector64<sbyte> right) => Or(left, right);
/// <summary>
/// float32x2_t vorr_f32 (float32x2_t a, float32x2_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector64<float> Or(Vector64<float> left, Vector64<float> right) => Or(left, right);
/// <summary>
/// uint16x4_t vorr_u16 (uint16x4_t a, uint16x4_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<ushort> Or(Vector64<ushort> left, Vector64<ushort> right) => Or(left, right);
/// <summary>
/// uint32x2_t vorr_u32 (uint32x2_t a, uint32x2_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<uint> Or(Vector64<uint> left, Vector64<uint> right) => Or(left, right);
- // /// <summary>
- // /// uint64x1_t vorr_u64 (uint64x1_t a, uint64x1_t b)
- // /// A32: VORR Dd, Dn, Dm
- // /// A64: ORR Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<ulong> Or(Vector64<ulong> left, Vector64<ulong> right) => Or(left, right);
-
/// <summary>
- /// uint8x16_t vorr_u8 (uint8x16_t a, uint8x16_t b)
+ /// uint64x1_t vorr_u64 (uint64x1_t a, uint64x1_t b)
/// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// A64: ORR Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<ulong> Or(Vector64<ulong> left, Vector64<ulong> right) => Or(left, right);
+
+ /// <summary>
+ /// uint8x16_t vorrq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<byte> Or(Vector128<byte> left, Vector128<byte> right) => Or(left, right);
/// <summary>
- /// float64x2_t vorr_f64 (float64x2_t a, float64x2_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// float64x2_t vorrq_f64 (float64x2_t a, float64x2_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<double> Or(Vector128<double> left, Vector128<double> right) => Or(left, right);
/// <summary>
- /// int16x8_t vorr_s16 (int16x8_t a, int16x8_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// int16x8_t vorrq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<short> Or(Vector128<short> left, Vector128<short> right) => Or(left, right);
/// <summary>
- /// int32x4_t vorr_s32(int32x4_t a, int32x4_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// int32x4_t vorrq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<int> Or(Vector128<int> left, Vector128<int> right) => Or(left, right);
/// <summary>
- /// int64x2_t vorr_s64 (int64x2_t a, int64x2_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// int64x2_t vorrq_s64 (int64x2_t a, int64x2_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<long> Or(Vector128<long> left, Vector128<long> right) => Or(left, right);
/// <summary>
- /// int8x16_t vorr_s8 (int8x16_t a, int8x16_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// int8x16_t vorrq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<sbyte> Or(Vector128<sbyte> left, Vector128<sbyte> right) => Or(left, right);
/// <summary>
- /// float32x4_t vorr_f32 (float32x4_t a, float32x4_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// float32x4_t vorrq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<float> Or(Vector128<float> left, Vector128<float> right) => Or(left, right);
/// <summary>
- /// uint16x8_t vorr_u16 (uint16x8_t a, uint16x8_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// uint16x8_t vorrq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ushort> Or(Vector128<ushort> left, Vector128<ushort> right) => Or(left, right);
/// <summary>
- /// uint32x4_t vorr_u32 (uint32x4_t a, uint32x4_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// uint32x4_t vorrq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<uint> Or(Vector128<uint> left, Vector128<uint> right) => Or(left, right);
/// <summary>
- /// uint64x2_t vorr_u64 (uint64x2_t a, uint64x2_t b)
- /// A32: VORR Dd, Dn, Dm
- /// A64: ORR Vd, Vn, Vm
+ /// uint64x2_t vorrq_u64 (uint64x2_t a, uint64x2_t b)
+ /// A32: VORR Qd, Qn, Qm
+ /// A64: ORR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ulong> Or(Vector128<ulong> left, Vector128<ulong> right) => Or(left, right);
/// <summary>
/// uint8x8_t vorn_u8 (uint8x8_t a, uint8x8_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<byte> OrNot(Vector64<byte> left, Vector64<byte> right) => OrNot(left, right);
- // /// <summary>
- // /// float64x1_t vorn_f64 (float64x1_t a, float64x1_t b)
- // /// A32: VORN Dd, Dn, Dm
- // /// A64: ORN Vd, Vn, Vm
- // /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
- // /// </summary>
- // public static Vector64<double> OrNot(Vector64<double> left, Vector64<double> right) => OrNot(left, right);
+ /// <summary>
+ /// float64x1_t vorn_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VORN Dd, Dn, Dm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<double> OrNot(Vector64<double> left, Vector64<double> right) => OrNot(left, right);
/// <summary>
/// int16x4_t vorn_s16 (int16x4_t a, int16x4_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<short> OrNot(Vector64<short> left, Vector64<short> right) => OrNot(left, right);
/// <summary>
- /// int32x2_t vorn_s32(int32x2_t a, int32x2_t b)
+ /// int32x2_t vorn_s32 (int32x2_t a, int32x2_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<int> OrNot(Vector64<int> left, Vector64<int> right) => OrNot(left, right);
- // /// <summary>
- // /// int64x1_t vorn_s64 (int64x1_t a, int64x1_t b)
- // /// A32: VORN Dd, Dn, Dm
- // /// A64: ORN Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<long> OrNot(Vector64<long> left, Vector64<long> right) => OrNot(left, right);
+ /// <summary>
+ /// int64x1_t vorn_s64 (int64x1_t a, int64x1_t b)
+ /// A32: VORN Dd, Dn, Dm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<long> OrNot(Vector64<long> left, Vector64<long> right) => OrNot(left, right);
/// <summary>
/// int8x8_t vorn_s8 (int8x8_t a, int8x8_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<sbyte> OrNot(Vector64<sbyte> left, Vector64<sbyte> right) => OrNot(left, right);
/// <summary>
/// float32x2_t vorn_f32 (float32x2_t a, float32x2_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector64<float> OrNot(Vector64<float> left, Vector64<float> right) => OrNot(left, right);
/// <summary>
/// uint16x4_t vorn_u16 (uint16x4_t a, uint16x4_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<ushort> OrNot(Vector64<ushort> left, Vector64<ushort> right) => OrNot(left, right);
/// <summary>
/// uint32x2_t vorn_u32 (uint32x2_t a, uint32x2_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<uint> OrNot(Vector64<uint> left, Vector64<uint> right) => OrNot(left, right);
- // /// <summary>
- // /// uint64x1_t vorn_u64 (uint64x1_t a, uint64x1_t b)
- // /// A32: VORN Dd, Dn, Dm
- // /// A64: ORN Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<ulong> OrNot(Vector64<ulong> left, Vector64<ulong> right) => OrNot(left, right);
-
/// <summary>
- /// uint8x16_t vorn_u8 (uint8x16_t a, uint8x16_t b)
+ /// uint64x1_t vorn_u64 (uint64x1_t a, uint64x1_t b)
/// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// A64: ORN Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<ulong> OrNot(Vector64<ulong> left, Vector64<ulong> right) => OrNot(left, right);
+
+ /// <summary>
+ /// uint8x16_t vornq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<byte> OrNot(Vector128<byte> left, Vector128<byte> right) => OrNot(left, right);
/// <summary>
- /// float64x2_t vorn_f64 (float64x2_t a, float64x2_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// float64x2_t vornq_f64 (float64x2_t a, float64x2_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<double> OrNot(Vector128<double> left, Vector128<double> right) => OrNot(left, right);
/// <summary>
- /// int16x8_t vorn_s16 (int16x8_t a, int16x8_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// int16x8_t vornq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<short> OrNot(Vector128<short> left, Vector128<short> right) => OrNot(left, right);
/// <summary>
- /// int32x4_t vorn_s32(int32x4_t a, int32x4_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// int32x4_t vornq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<int> OrNot(Vector128<int> left, Vector128<int> right) => OrNot(left, right);
/// <summary>
- /// int64x2_t vorn_s64 (int64x2_t a, int64x2_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// int64x2_t vornq_s64 (int64x2_t a, int64x2_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<long> OrNot(Vector128<long> left, Vector128<long> right) => OrNot(left, right);
/// <summary>
- /// int8x16_t vorn_s8 (int8x16_t a, int8x16_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// int8x16_t vornq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<sbyte> OrNot(Vector128<sbyte> left, Vector128<sbyte> right) => OrNot(left, right);
/// <summary>
- /// float32x4_t vorn_f32 (float32x4_t a, float32x4_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// float32x4_t vornq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<float> OrNot(Vector128<float> left, Vector128<float> right) => OrNot(left, right);
/// <summary>
- /// uint16x8_t vorn_u16 (uint16x8_t a, uint16x8_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// uint16x8_t vornq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ushort> OrNot(Vector128<ushort> left, Vector128<ushort> right) => OrNot(left, right);
/// <summary>
- /// uint32x4_t vorn_u32 (uint32x4_t a, uint32x4_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// uint32x4_t vornq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<uint> OrNot(Vector128<uint> left, Vector128<uint> right) => OrNot(left, right);
/// <summary>
- /// uint64x2_t vorn_u64 (uint64x2_t a, uint64x2_t b)
- /// A32: VORN Dd, Dn, Dm
- /// A64: ORN Vd, Vn, Vm
+ /// uint64x2_t vornq_u64 (uint64x2_t a, uint64x2_t b)
+ /// A32: VORN Qd, Qn, Qm
+ /// A64: ORN Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ulong> OrNot(Vector128<ulong> left, Vector128<ulong> right) => OrNot(left, right);
public static Vector128<sbyte> PopCount(Vector128<sbyte> value) => PopCount(value);
/// <summary>
+ /// float64x1_t vsqrt_f64 (float64x1_t a)
+ /// A32: VSQRT.F64 Dd, Dm
+ /// A64: FSQRT Dd, Dn
+ /// </summary>
+ public static Vector64<double> SqrtScalar(Vector64<double> value) => SqrtScalar(value);
+
+ /// <summary>
+ /// float32_t vsqrts_f32 (float32_t a)
+ /// A32: VSQRT.F32 Sd, Sm
+ /// A64: FSQRT Sd, Sn
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<float> SqrtScalar(Vector64<float> value) => SqrtScalar(value);
+
+ /// <summary>
/// uint8x8_t vsub_u8 (uint8x8_t a, uint8x8_t b)
/// A32: VSUB.I8 Dd, Dn, Dm
- /// A64: ADD Vd.8B, Vn.8B, Vm.8B
+ /// A64: SUB Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<byte> Subtract(Vector64<byte> left, Vector64<byte> right) => Subtract(left, right);
/// <summary>
/// int16x4_t vsub_s16 (int16x4_t a, int16x4_t b)
/// A32: VSUB.I16 Dd, Dn, Dm
- /// A64: ADD Vd.4H, Vn.4H, Vm.4H
+ /// A64: SUB Vd.4H, Vn.4H, Vm.4H
/// </summary>
public static Vector64<short> Subtract(Vector64<short> left, Vector64<short> right) => Subtract(left, right);
/// <summary>
/// int32x2_t vsub_s32 (int32x2_t a, int32x2_t b)
/// A32: VSUB.I32 Dd, Dn, Dm
- /// A64: ADD Vd.2S, Vn.2S, Vm.2S
+ /// A64: SUB Vd.2S, Vn.2S, Vm.2S
/// </summary>
public static Vector64<int> Subtract(Vector64<int> left, Vector64<int> right) => Subtract(left, right);
/// <summary>
/// int8x8_t vsub_s8 (int8x8_t a, int8x8_t b)
/// A32: VSUB.I8 Dd, Dn, Dm
- /// A64: ADD Vd.8B, Vn.8B, Vm.8B
+ /// A64: SUB Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<sbyte> Subtract(Vector64<sbyte> left, Vector64<sbyte> right) => Subtract(left, right);
/// <summary>
/// uint16x4_t vsub_u16 (uint16x4_t a, uint16x4_t b)
/// A32: VSUB.I16 Dd, Dn, Dm
- /// A64: ADD Vd.4H, Vn.4H, Vm.4H
+ /// A64: SUB Vd.4H, Vn.4H, Vm.4H
/// </summary>
public static Vector64<ushort> Subtract(Vector64<ushort> left, Vector64<ushort> right) => Subtract(left, right);
/// <summary>
/// uint32x2_t vsub_u32 (uint32x2_t a, uint32x2_t b)
/// A32: VSUB.I32 Dd, Dn, Dm
- /// A64: ADD Vd.2S, Vn.2S, Vm.2S
+ /// A64: SUB Vd.2S, Vn.2S, Vm.2S
/// </summary>
public static Vector64<uint> Subtract(Vector64<uint> left, Vector64<uint> right) => Subtract(left, right);
/// <summary>
/// uint8x16_t vsubq_u8 (uint8x16_t a, uint8x16_t b)
/// A32: VSUB.I8 Qd, Qn, Qm
- /// A64: ADD Vd.16B, Vn.16B, Vm.16B
+ /// A64: SUB Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<byte> Subtract(Vector128<byte> left, Vector128<byte> right) => Subtract(left, right);
/// <summary>
/// int16x8_t vsubq_s16 (int16x8_t a, int16x8_t b)
/// A32: VSUB.I16 Qd, Qn, Qm
- /// A64: ADD Vd.8H, Vn.8H, Vm.8H
+ /// A64: SUB Vd.8H, Vn.8H, Vm.8H
/// </summary>
public static Vector128<short> Subtract(Vector128<short> left, Vector128<short> right) => Subtract(left, right);
/// <summary>
/// int32x4_t vsubq_s32 (int32x4_t a, int32x4_t b)
/// A32: VSUB.I32 Qd, Qn, Qm
- /// A64: ADD Vd.4S, Vn.4S, Vm.4S
+ /// A64: SUB Vd.4S, Vn.4S, Vm.4S
/// </summary>
public static Vector128<int> Subtract(Vector128<int> left, Vector128<int> right) => Subtract(left, right);
/// <summary>
/// int64x2_t vsubq_s64 (int64x2_t a, int64x2_t b)
/// A32: VSUB.I64 Qd, Qn, Qm
- /// A64: ADD Vd.2D, Vn.2D, Vm.2D
+ /// A64: SUB Vd.2D, Vn.2D, Vm.2D
/// </summary>
public static Vector128<long> Subtract(Vector128<long> left, Vector128<long> right) => Subtract(left, right);
/// <summary>
/// int8x16_t vsubq_s8 (int8x16_t a, int8x16_t b)
/// A32: VSUB.I8 Qd, Qn, Qm
- /// A64: ADD Vd.16B, Vn.16B, Vm.16B
+ /// A64: SUB Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<sbyte> Subtract(Vector128<sbyte> left, Vector128<sbyte> right) => Subtract(left, right);
/// <summary>
/// uint16x8_t vsubq_u16 (uint16x8_t a, uint16x8_t b)
/// A32: VSUB.I16 Qd, Qn, Qm
- /// A64: ADD Vd.8H, Vn.8H, Vm.8H
+ /// A64: SUB Vd.8H, Vn.8H, Vm.8H
/// </summary>
public static Vector128<ushort> Subtract(Vector128<ushort> left, Vector128<ushort> right) => Subtract(left, right);
/// <summary>
/// uint32x4_t vsubq_u32 (uint32x4_t a, uint32x4_t b)
/// A32: VSUB.I32 Qd, Qn, Qm
- /// A64: ADD Vd.4S, Vn.4S, Vm.4S
+ /// A64: SUB Vd.4S, Vn.4S, Vm.4S
/// </summary>
public static Vector128<uint> Subtract(Vector128<uint> left, Vector128<uint> right) => Subtract(left, right);
/// <summary>
/// uint64x2_t vsubq_u64 (uint64x2_t a, uint64x2_t b)
/// A32: VSUB.I64 Qd, Qn, Qm
- /// A64: ADD Vd.2D, Vn.2D, Vm.2D
+ /// A64: SUB Vd.2D, Vn.2D, Vm.2D
/// </summary>
public static Vector128<ulong> Subtract(Vector128<ulong> left, Vector128<ulong> right) => Subtract(left, right);
- // /// <summary>
- // /// float64x1_t vsub_f64 (float64x1_t a, float64x1_t b)
- // /// A32: VSUB.F64 Dd, Dn, Dm
- // /// A64: FSUB Dd, Dn, Dm
- // /// </summary>
- // public static Vector64<double> SubtractScalar(Vector64<double> left, Vector64<double> right) => Subtract(left, right);
-
- // /// <summary>
- // /// int64x1_t vsub_s64 (int64x1_t a, int64x1_t b)
- // /// A32: VSUB.I64 Dd, Dn, Dm
- // /// A64: ADD Dd, Dn, Dm
- // /// </summary>
- // public static Vector64<long> SubtractScalar(Vector64<long> left, Vector64<long> right) => SubtractScalar(left, right);
+ /// <summary>
+ /// float64x1_t vsub_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VSUB.F64 Dd, Dn, Dm
+ /// A64: FSUB Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<double> SubtractScalar(Vector64<double> left, Vector64<double> right) => SubtractScalar(left, right);
- // /// <summary>
- // /// uint64x1_t vsub_u64 (uint64x1_t a, uint64x1_t b)
- // /// A32: VSUB.I64 Dd, Dn, Dm
- // /// A64: ADD Dd, Dn, Dm
- // /// </summary>
- // public static Vector64<ulong> SubtractScalar(Vector64<ulong> left, Vector64<ulong> right) => SubtractScalar(left, right);
+ /// <summary>
+ /// int64x1_t vsub_s64 (int64x1_t a, int64x1_t b)
+ /// A32: VSUB.I64 Dd, Dn, Dm
+ /// A64: SUB Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<long> SubtractScalar(Vector64<long> left, Vector64<long> right) => SubtractScalar(left, right);
/// <summary>
+ /// float32_t vsubs_f32 (float32_t a, float32_t b)
/// A32: VSUB.F32 Sd, Sn, Sm
- /// A64:
+ /// A64: FSUB Sd, Sn, Sm
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector64<float> SubtractScalar(Vector64<float> left, Vector64<float> right) => SubtractScalar(left, right);
/// <summary>
+ /// uint64x1_t vsub_u64 (uint64x1_t a, uint64x1_t b)
+ /// A32: VSUB.I64 Dd, Dn, Dm
+ /// A64: SUB Dd, Dn, Dm
+ /// </summary>
+ public static Vector64<ulong> SubtractScalar(Vector64<ulong> left, Vector64<ulong> right) => SubtractScalar(left, right);
+
+ /// <summary>
/// uint8x8_t veor_u8 (uint8x8_t a, uint8x8_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<byte> Xor(Vector64<byte> left, Vector64<byte> right) => Xor(left, right);
- // /// <summary>
- // /// float64x1_t veor_f64 (float64x1_t a, float64x1_t b)
- // /// A32: VEOR Dd, Dn, Dm
- // /// A64: EOR Vd, Vn, Vm
- // /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
- // /// </summary>
- // public static Vector64<double> Xor(Vector64<double> left, Vector64<double> right) => Xor(left, right);
+ /// <summary>
+ /// float64x1_t veor_f64 (float64x1_t a, float64x1_t b)
+ /// A32: VEOR Dd, Dn, Dm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector64<double> Xor(Vector64<double> left, Vector64<double> right) => Xor(left, right);
/// <summary>
/// int16x4_t veor_s16 (int16x4_t a, int16x4_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<short> Xor(Vector64<short> left, Vector64<short> right) => Xor(left, right);
/// <summary>
- /// int32x2_t veor_s32(int32x2_t a, int32x2_t b)
+ /// int32x2_t veor_s32 (int32x2_t a, int32x2_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<int> Xor(Vector64<int> left, Vector64<int> right) => Xor(left, right);
- // /// <summary>
- // /// int64x1_t veor_s64 (int64x1_t a, int64x1_t b)
- // /// A32: VEOR Dd, Dn, Dm
- // /// A64: EOR Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<long> Xor(Vector64<long> left, Vector64<long> right) => Xor(left, right);
+ /// <summary>
+ /// int64x1_t veor_s64 (int64x1_t a, int64x1_t b)
+ /// A32: VEOR Dd, Dn, Dm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<long> Xor(Vector64<long> left, Vector64<long> right) => Xor(left, right);
/// <summary>
/// int8x8_t veor_s8 (int8x8_t a, int8x8_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<sbyte> Xor(Vector64<sbyte> left, Vector64<sbyte> right) => Xor(left, right);
/// <summary>
/// float32x2_t veor_f32 (float32x2_t a, float32x2_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector64<float> Xor(Vector64<float> left, Vector64<float> right) => Xor(left, right);
/// <summary>
/// uint16x4_t veor_u16 (uint16x4_t a, uint16x4_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<ushort> Xor(Vector64<ushort> left, Vector64<ushort> right) => Xor(left, right);
/// <summary>
/// uint32x2_t veor_u32 (uint32x2_t a, uint32x2_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
/// </summary>
public static Vector64<uint> Xor(Vector64<uint> left, Vector64<uint> right) => Xor(left, right);
- // /// <summary>
- // /// uint64x1_t veor_u64 (uint64x1_t a, uint64x1_t b)
- // /// A32: VEOR Dd, Dn, Dm
- // /// A64: EOR Vd, Vn, Vm
- // /// </summary>
- // public static Vector64<ulong> Xor(Vector64<ulong> left, Vector64<ulong> right) => Xor(left, right);
-
/// <summary>
- /// uint8x16_t veor_u8 (uint8x16_t a, uint8x16_t b)
+ /// uint64x1_t veor_u64 (uint64x1_t a, uint64x1_t b)
/// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// A64: EOR Vd.8B, Vn.8B, Vm.8B
+ /// </summary>
+ public static Vector64<ulong> Xor(Vector64<ulong> left, Vector64<ulong> right) => Xor(left, right);
+
+ /// <summary>
+ /// uint8x16_t veorq_u8 (uint8x16_t a, uint8x16_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<byte> Xor(Vector128<byte> left, Vector128<byte> right) => Xor(left, right);
/// <summary>
- /// float64x2_t veor_f64 (float64x2_t a, float64x2_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// float64x2_t veorq_f64 (float64x2_t a, float64x2_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<double> Xor(Vector128<double> left, Vector128<double> right) => Xor(left, right);
/// <summary>
- /// int16x8_t veor_s16 (int16x8_t a, int16x8_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// int16x8_t veorq_s16 (int16x8_t a, int16x8_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<short> Xor(Vector128<short> left, Vector128<short> right) => Xor(left, right);
/// <summary>
- /// int32x4_t veor_s32(int32x4_t a, int32x4_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// int32x4_t veorq_s32 (int32x4_t a, int32x4_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<int> Xor(Vector128<int> left, Vector128<int> right) => Xor(left, right);
/// <summary>
- /// int64x2_t veor_s64 (int64x2_t a, int64x2_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// int64x2_t veorq_s64 (int64x2_t a, int64x2_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<long> Xor(Vector128<long> left, Vector128<long> right) => Xor(left, right);
/// <summary>
- /// int8x16_t veor_s8 (int8x16_t a, int8x16_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// int8x16_t veorq_s8 (int8x16_t a, int8x16_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<sbyte> Xor(Vector128<sbyte> left, Vector128<sbyte> right) => Xor(left, right);
/// <summary>
- /// float32x4_t veor_f32 (float32x4_t a, float32x4_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// float32x4_t veorq_f32 (float32x4_t a, float32x4_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
/// </summary>
public static Vector128<float> Xor(Vector128<float> left, Vector128<float> right) => Xor(left, right);
/// <summary>
- /// uint16x8_t veor_u16 (uint16x8_t a, uint16x8_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// uint16x8_t veorq_u16 (uint16x8_t a, uint16x8_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ushort> Xor(Vector128<ushort> left, Vector128<ushort> right) => Xor(left, right);
/// <summary>
- /// uint32x4_t veor_u32 (uint32x4_t a, uint32x4_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// uint32x4_t veorq_u32 (uint32x4_t a, uint32x4_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<uint> Xor(Vector128<uint> left, Vector128<uint> right) => Xor(left, right);
/// <summary>
- /// uint64x2_t veor_u64 (uint64x2_t a, uint64x2_t b)
- /// A32: VEOR Dd, Dn, Dm
- /// A64: EOR Vd, Vn, Vm
+ /// uint64x2_t veorq_u64 (uint64x2_t a, uint64x2_t b)
+ /// A32: VEOR Qd, Qn, Qm
+ /// A64: EOR Vd.16B, Vn.16B, Vm.16B
/// </summary>
public static Vector128<ulong> Xor(Vector128<ulong> left, Vector128<ulong> right) => Xor(left, right);
}
public static System.Runtime.Intrinsics.Vector128<uint> And(System.Runtime.Intrinsics.Vector128<uint> left, System.Runtime.Intrinsics.Vector128<uint> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<ulong> And(System.Runtime.Intrinsics.Vector128<ulong> left, System.Runtime.Intrinsics.Vector128<ulong> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<byte> And(System.Runtime.Intrinsics.Vector64<byte> left, System.Runtime.Intrinsics.Vector64<byte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<double> And(System.Runtime.Intrinsics.Vector64<double> left, System.Runtime.Intrinsics.Vector64<double> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<short> And(System.Runtime.Intrinsics.Vector64<short> left, System.Runtime.Intrinsics.Vector64<short> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<int> And(System.Runtime.Intrinsics.Vector64<int> left, System.Runtime.Intrinsics.Vector64<int> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<long> And(System.Runtime.Intrinsics.Vector64<long> left, System.Runtime.Intrinsics.Vector64<long> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<sbyte> And(System.Runtime.Intrinsics.Vector64<sbyte> left, System.Runtime.Intrinsics.Vector64<sbyte> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<float> And(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<ushort> And(System.Runtime.Intrinsics.Vector64<ushort> left, System.Runtime.Intrinsics.Vector64<ushort> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<uint> And(System.Runtime.Intrinsics.Vector64<uint> left, System.Runtime.Intrinsics.Vector64<uint> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector128<byte> AndNot(System.Runtime.Intrinsics.Vector128<byte> left, System.Runtime.Intrinsics.Vector128<byte> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector128<double> AndNot(System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector128<short> AndNot(System.Runtime.Intrinsics.Vector128<short> left, System.Runtime.Intrinsics.Vector128<short> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector128<int> AndNot(System.Runtime.Intrinsics.Vector128<int> left, System.Runtime.Intrinsics.Vector128<int> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector128<long> AndNot(System.Runtime.Intrinsics.Vector128<long> left, System.Runtime.Intrinsics.Vector128<long> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector128<sbyte> AndNot(System.Runtime.Intrinsics.Vector128<sbyte> left, System.Runtime.Intrinsics.Vector128<sbyte> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector128<float> AndNot(System.Runtime.Intrinsics.Vector128<float> left, System.Runtime.Intrinsics.Vector128<float> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector128<ushort> AndNot(System.Runtime.Intrinsics.Vector128<ushort> left, System.Runtime.Intrinsics.Vector128<ushort> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector128<uint> AndNot(System.Runtime.Intrinsics.Vector128<uint> left, System.Runtime.Intrinsics.Vector128<uint> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector128<ulong> AndNot(System.Runtime.Intrinsics.Vector128<ulong> left, System.Runtime.Intrinsics.Vector128<ulong> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector64<byte> AndNot(System.Runtime.Intrinsics.Vector64<byte> left, System.Runtime.Intrinsics.Vector64<byte> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector64<short> AndNot(System.Runtime.Intrinsics.Vector64<short> left, System.Runtime.Intrinsics.Vector64<short> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector64<int> AndNot(System.Runtime.Intrinsics.Vector64<int> left, System.Runtime.Intrinsics.Vector64<int> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector64<sbyte> AndNot(System.Runtime.Intrinsics.Vector64<sbyte> left, System.Runtime.Intrinsics.Vector64<sbyte> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector64<float> AndNot(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector64<ushort> AndNot(System.Runtime.Intrinsics.Vector64<ushort> left, System.Runtime.Intrinsics.Vector64<ushort> right) { throw null; }
- public static System.Runtime.Intrinsics.Vector64<uint> AndNot(System.Runtime.Intrinsics.Vector64<uint> left, System.Runtime.Intrinsics.Vector64<uint> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<ulong> And(System.Runtime.Intrinsics.Vector64<ulong> left, System.Runtime.Intrinsics.Vector64<ulong> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<byte> BitwiseClear(System.Runtime.Intrinsics.Vector128<byte> value, System.Runtime.Intrinsics.Vector128<byte> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<double> BitwiseClear(System.Runtime.Intrinsics.Vector128<double> value, System.Runtime.Intrinsics.Vector128<double> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<short> BitwiseClear(System.Runtime.Intrinsics.Vector128<short> value, System.Runtime.Intrinsics.Vector128<short> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<int> BitwiseClear(System.Runtime.Intrinsics.Vector128<int> value, System.Runtime.Intrinsics.Vector128<int> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<long> BitwiseClear(System.Runtime.Intrinsics.Vector128<long> value, System.Runtime.Intrinsics.Vector128<long> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<sbyte> BitwiseClear(System.Runtime.Intrinsics.Vector128<sbyte> value, System.Runtime.Intrinsics.Vector128<sbyte> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<float> BitwiseClear(System.Runtime.Intrinsics.Vector128<float> value, System.Runtime.Intrinsics.Vector128<float> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<ushort> BitwiseClear(System.Runtime.Intrinsics.Vector128<ushort> value, System.Runtime.Intrinsics.Vector128<ushort> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<uint> BitwiseClear(System.Runtime.Intrinsics.Vector128<uint> value, System.Runtime.Intrinsics.Vector128<uint> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<ulong> BitwiseClear(System.Runtime.Intrinsics.Vector128<ulong> value, System.Runtime.Intrinsics.Vector128<ulong> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<byte> BitwiseClear(System.Runtime.Intrinsics.Vector64<byte> value, System.Runtime.Intrinsics.Vector64<byte> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<double> BitwiseClear(System.Runtime.Intrinsics.Vector64<double> value, System.Runtime.Intrinsics.Vector64<double> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<short> BitwiseClear(System.Runtime.Intrinsics.Vector64<short> value, System.Runtime.Intrinsics.Vector64<short> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<int> BitwiseClear(System.Runtime.Intrinsics.Vector64<int> value, System.Runtime.Intrinsics.Vector64<int> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<long> BitwiseClear(System.Runtime.Intrinsics.Vector64<long> value, System.Runtime.Intrinsics.Vector64<long> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<sbyte> BitwiseClear(System.Runtime.Intrinsics.Vector64<sbyte> value, System.Runtime.Intrinsics.Vector64<sbyte> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<float> BitwiseClear(System.Runtime.Intrinsics.Vector64<float> value, System.Runtime.Intrinsics.Vector64<float> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<ushort> BitwiseClear(System.Runtime.Intrinsics.Vector64<ushort> value, System.Runtime.Intrinsics.Vector64<ushort> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<uint> BitwiseClear(System.Runtime.Intrinsics.Vector64<uint> value, System.Runtime.Intrinsics.Vector64<uint> mask) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<ulong> BitwiseClear(System.Runtime.Intrinsics.Vector64<ulong> value, System.Runtime.Intrinsics.Vector64<ulong> mask) { throw null; }
public static System.Runtime.Intrinsics.Vector128<byte> BitwiseSelect(System.Runtime.Intrinsics.Vector128<byte> select, System.Runtime.Intrinsics.Vector128<byte> left, System.Runtime.Intrinsics.Vector128<byte> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<double> BitwiseSelect(System.Runtime.Intrinsics.Vector128<double> select, System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<short> BitwiseSelect(System.Runtime.Intrinsics.Vector128<short> select, System.Runtime.Intrinsics.Vector128<short> left, System.Runtime.Intrinsics.Vector128<short> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<float> CompareTest(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<ushort> CompareTest(System.Runtime.Intrinsics.Vector64<ushort> left, System.Runtime.Intrinsics.Vector64<ushort> right) { throw null; }
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.Vector128<short> LeadingSignCount(System.Runtime.Intrinsics.Vector128<short> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<int> LeadingSignCount(System.Runtime.Intrinsics.Vector128<int> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<sbyte> LeadingSignCount(System.Runtime.Intrinsics.Vector128<sbyte> value) { throw null; }
public unsafe static System.Runtime.Intrinsics.Vector64<ushort> LoadVector64(ushort* address) { throw null; }
public unsafe static System.Runtime.Intrinsics.Vector64<uint> LoadVector64(uint* address) { throw null; }
public unsafe static System.Runtime.Intrinsics.Vector64<ulong> LoadVector64(ulong* address) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<byte> Max(System.Runtime.Intrinsics.Vector128<byte> left, System.Runtime.Intrinsics.Vector128<byte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<short> Max(System.Runtime.Intrinsics.Vector128<short> left, System.Runtime.Intrinsics.Vector128<short> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<int> Max(System.Runtime.Intrinsics.Vector128<int> left, System.Runtime.Intrinsics.Vector128<int> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<sbyte> Max(System.Runtime.Intrinsics.Vector128<sbyte> left, System.Runtime.Intrinsics.Vector128<sbyte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<float> Max(System.Runtime.Intrinsics.Vector128<float> left, System.Runtime.Intrinsics.Vector128<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<ushort> Max(System.Runtime.Intrinsics.Vector128<ushort> left, System.Runtime.Intrinsics.Vector128<ushort> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<uint> Max(System.Runtime.Intrinsics.Vector128<uint> left, System.Runtime.Intrinsics.Vector128<uint> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<byte> Max(System.Runtime.Intrinsics.Vector64<byte> left, System.Runtime.Intrinsics.Vector64<byte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<short> Max(System.Runtime.Intrinsics.Vector64<short> left, System.Runtime.Intrinsics.Vector64<short> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<int> Max(System.Runtime.Intrinsics.Vector64<int> left, System.Runtime.Intrinsics.Vector64<int> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<sbyte> Max(System.Runtime.Intrinsics.Vector64<sbyte> left, System.Runtime.Intrinsics.Vector64<sbyte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<float> Max(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<ushort> Max(System.Runtime.Intrinsics.Vector64<ushort> left, System.Runtime.Intrinsics.Vector64<ushort> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<uint> Max(System.Runtime.Intrinsics.Vector64<uint> left, System.Runtime.Intrinsics.Vector64<uint> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<byte> Min(System.Runtime.Intrinsics.Vector128<byte> left, System.Runtime.Intrinsics.Vector128<byte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<short> Min(System.Runtime.Intrinsics.Vector128<short> left, System.Runtime.Intrinsics.Vector128<short> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<int> Min(System.Runtime.Intrinsics.Vector128<int> left, System.Runtime.Intrinsics.Vector128<int> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<sbyte> Min(System.Runtime.Intrinsics.Vector128<sbyte> left, System.Runtime.Intrinsics.Vector128<sbyte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<float> Min(System.Runtime.Intrinsics.Vector128<float> left, System.Runtime.Intrinsics.Vector128<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<ushort> Min(System.Runtime.Intrinsics.Vector128<ushort> left, System.Runtime.Intrinsics.Vector128<ushort> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<uint> Min(System.Runtime.Intrinsics.Vector128<uint> left, System.Runtime.Intrinsics.Vector128<uint> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<byte> Min(System.Runtime.Intrinsics.Vector64<byte> left, System.Runtime.Intrinsics.Vector64<byte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<short> Min(System.Runtime.Intrinsics.Vector64<short> left, System.Runtime.Intrinsics.Vector64<short> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<int> Min(System.Runtime.Intrinsics.Vector64<int> left, System.Runtime.Intrinsics.Vector64<int> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<sbyte> Min(System.Runtime.Intrinsics.Vector64<sbyte> left, System.Runtime.Intrinsics.Vector64<sbyte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<float> Min(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<ushort> Min(System.Runtime.Intrinsics.Vector64<ushort> left, System.Runtime.Intrinsics.Vector64<ushort> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<uint> Min(System.Runtime.Intrinsics.Vector64<uint> left, System.Runtime.Intrinsics.Vector64<uint> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<byte> Multiply(System.Runtime.Intrinsics.Vector128<byte> left, System.Runtime.Intrinsics.Vector128<byte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<short> Multiply(System.Runtime.Intrinsics.Vector128<short> left, System.Runtime.Intrinsics.Vector128<short> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<int> Multiply(System.Runtime.Intrinsics.Vector128<int> left, System.Runtime.Intrinsics.Vector128<int> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<sbyte> Multiply(System.Runtime.Intrinsics.Vector128<sbyte> left, System.Runtime.Intrinsics.Vector128<sbyte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<float> Multiply(System.Runtime.Intrinsics.Vector128<float> left, System.Runtime.Intrinsics.Vector128<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<ushort> Multiply(System.Runtime.Intrinsics.Vector128<ushort> left, System.Runtime.Intrinsics.Vector128<ushort> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<uint> Multiply(System.Runtime.Intrinsics.Vector128<uint> left, System.Runtime.Intrinsics.Vector128<uint> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<byte> Multiply(System.Runtime.Intrinsics.Vector64<byte> left, System.Runtime.Intrinsics.Vector64<byte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<short> Multiply(System.Runtime.Intrinsics.Vector64<short> left, System.Runtime.Intrinsics.Vector64<short> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<int> Multiply(System.Runtime.Intrinsics.Vector64<int> left, System.Runtime.Intrinsics.Vector64<int> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<sbyte> Multiply(System.Runtime.Intrinsics.Vector64<sbyte> left, System.Runtime.Intrinsics.Vector64<sbyte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<float> Multiply(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<ushort> Multiply(System.Runtime.Intrinsics.Vector64<ushort> left, System.Runtime.Intrinsics.Vector64<ushort> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<uint> Multiply(System.Runtime.Intrinsics.Vector64<uint> left, System.Runtime.Intrinsics.Vector64<uint> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<double> MultiplyScalar(System.Runtime.Intrinsics.Vector64<double> left, System.Runtime.Intrinsics.Vector64<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<float> MultiplyScalar(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<short> Negate(System.Runtime.Intrinsics.Vector128<short> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<int> Negate(System.Runtime.Intrinsics.Vector128<int> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<sbyte> Negate(System.Runtime.Intrinsics.Vector128<sbyte> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<float> Negate(System.Runtime.Intrinsics.Vector128<float> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<short> Negate(System.Runtime.Intrinsics.Vector64<short> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<int> Negate(System.Runtime.Intrinsics.Vector64<int> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<sbyte> Negate(System.Runtime.Intrinsics.Vector64<sbyte> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<float> Negate(System.Runtime.Intrinsics.Vector64<float> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<double> NegateScalar(System.Runtime.Intrinsics.Vector64<double> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<float> NegateScalar(System.Runtime.Intrinsics.Vector64<float> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<byte> Not(System.Runtime.Intrinsics.Vector128<byte> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<double> Not(System.Runtime.Intrinsics.Vector128<double> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<short> Not(System.Runtime.Intrinsics.Vector128<short> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<uint> Not(System.Runtime.Intrinsics.Vector128<uint> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<ulong> Not(System.Runtime.Intrinsics.Vector128<ulong> value) { throw null; }
public static System.Runtime.Intrinsics.Vector64<byte> Not(System.Runtime.Intrinsics.Vector64<byte> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<double> Not(System.Runtime.Intrinsics.Vector64<double> value) { throw null; }
public static System.Runtime.Intrinsics.Vector64<short> Not(System.Runtime.Intrinsics.Vector64<short> value) { throw null; }
public static System.Runtime.Intrinsics.Vector64<int> Not(System.Runtime.Intrinsics.Vector64<int> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<long> Not(System.Runtime.Intrinsics.Vector64<long> value) { throw null; }
public static System.Runtime.Intrinsics.Vector64<sbyte> Not(System.Runtime.Intrinsics.Vector64<sbyte> value) { throw null; }
public static System.Runtime.Intrinsics.Vector64<float> Not(System.Runtime.Intrinsics.Vector64<float> value) { throw null; }
public static System.Runtime.Intrinsics.Vector64<ushort> Not(System.Runtime.Intrinsics.Vector64<ushort> value) { throw null; }
public static System.Runtime.Intrinsics.Vector64<uint> Not(System.Runtime.Intrinsics.Vector64<uint> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<ulong> Not(System.Runtime.Intrinsics.Vector64<ulong> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<byte> Or(System.Runtime.Intrinsics.Vector128<byte> left, System.Runtime.Intrinsics.Vector128<byte> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<double> Or(System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<short> Or(System.Runtime.Intrinsics.Vector128<short> left, System.Runtime.Intrinsics.Vector128<short> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<uint> Or(System.Runtime.Intrinsics.Vector128<uint> left, System.Runtime.Intrinsics.Vector128<uint> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<ulong> Or(System.Runtime.Intrinsics.Vector128<ulong> left, System.Runtime.Intrinsics.Vector128<ulong> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<byte> Or(System.Runtime.Intrinsics.Vector64<byte> left, System.Runtime.Intrinsics.Vector64<byte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<double> Or(System.Runtime.Intrinsics.Vector64<double> left, System.Runtime.Intrinsics.Vector64<double> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<short> Or(System.Runtime.Intrinsics.Vector64<short> left, System.Runtime.Intrinsics.Vector64<short> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<int> Or(System.Runtime.Intrinsics.Vector64<int> left, System.Runtime.Intrinsics.Vector64<int> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<long> Or(System.Runtime.Intrinsics.Vector64<long> left, System.Runtime.Intrinsics.Vector64<long> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<sbyte> Or(System.Runtime.Intrinsics.Vector64<sbyte> left, System.Runtime.Intrinsics.Vector64<sbyte> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<float> Or(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<ushort> Or(System.Runtime.Intrinsics.Vector64<ushort> left, System.Runtime.Intrinsics.Vector64<ushort> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<uint> Or(System.Runtime.Intrinsics.Vector64<uint> left, System.Runtime.Intrinsics.Vector64<uint> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<ulong> Or(System.Runtime.Intrinsics.Vector64<ulong> left, System.Runtime.Intrinsics.Vector64<ulong> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<byte> OrNot(System.Runtime.Intrinsics.Vector128<byte> left, System.Runtime.Intrinsics.Vector128<byte> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<double> OrNot(System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<short> OrNot(System.Runtime.Intrinsics.Vector128<short> left, System.Runtime.Intrinsics.Vector128<short> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<uint> OrNot(System.Runtime.Intrinsics.Vector128<uint> left, System.Runtime.Intrinsics.Vector128<uint> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<ulong> OrNot(System.Runtime.Intrinsics.Vector128<ulong> left, System.Runtime.Intrinsics.Vector128<ulong> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<byte> OrNot(System.Runtime.Intrinsics.Vector64<byte> left, System.Runtime.Intrinsics.Vector64<byte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<double> OrNot(System.Runtime.Intrinsics.Vector64<double> left, System.Runtime.Intrinsics.Vector64<double> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<short> OrNot(System.Runtime.Intrinsics.Vector64<short> left, System.Runtime.Intrinsics.Vector64<short> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<int> OrNot(System.Runtime.Intrinsics.Vector64<int> left, System.Runtime.Intrinsics.Vector64<int> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<long> OrNot(System.Runtime.Intrinsics.Vector64<long> left, System.Runtime.Intrinsics.Vector64<long> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<sbyte> OrNot(System.Runtime.Intrinsics.Vector64<sbyte> left, System.Runtime.Intrinsics.Vector64<sbyte> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<float> OrNot(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<ushort> OrNot(System.Runtime.Intrinsics.Vector64<ushort> left, System.Runtime.Intrinsics.Vector64<ushort> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<uint> OrNot(System.Runtime.Intrinsics.Vector64<uint> left, System.Runtime.Intrinsics.Vector64<uint> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<ulong> OrNot(System.Runtime.Intrinsics.Vector64<ulong> left, System.Runtime.Intrinsics.Vector64<ulong> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<byte> PopCount(System.Runtime.Intrinsics.Vector128<byte> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<sbyte> PopCount(System.Runtime.Intrinsics.Vector128<sbyte> value) { throw null; }
public static System.Runtime.Intrinsics.Vector64<byte> PopCount(System.Runtime.Intrinsics.Vector64<byte> value) { throw null; }
public static System.Runtime.Intrinsics.Vector64<sbyte> PopCount(System.Runtime.Intrinsics.Vector64<sbyte> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<double> SqrtScalar(System.Runtime.Intrinsics.Vector64<double> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<float> SqrtScalar(System.Runtime.Intrinsics.Vector64<float> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<byte> Subtract(System.Runtime.Intrinsics.Vector128<byte> left, System.Runtime.Intrinsics.Vector128<byte> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<short> Subtract(System.Runtime.Intrinsics.Vector128<short> left, System.Runtime.Intrinsics.Vector128<short> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<int> Subtract(System.Runtime.Intrinsics.Vector128<int> left, System.Runtime.Intrinsics.Vector128<int> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<float> Subtract(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<ushort> Subtract(System.Runtime.Intrinsics.Vector64<ushort> left, System.Runtime.Intrinsics.Vector64<ushort> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<uint> Subtract(System.Runtime.Intrinsics.Vector64<uint> left, System.Runtime.Intrinsics.Vector64<uint> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<double> SubtractScalar(System.Runtime.Intrinsics.Vector64<double> left, System.Runtime.Intrinsics.Vector64<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<long> SubtractScalar(System.Runtime.Intrinsics.Vector64<long> left, System.Runtime.Intrinsics.Vector64<long> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<float> SubtractScalar(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<ulong> SubtractScalar(System.Runtime.Intrinsics.Vector64<ulong> left, System.Runtime.Intrinsics.Vector64<ulong> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<byte> Xor(System.Runtime.Intrinsics.Vector128<byte> left, System.Runtime.Intrinsics.Vector128<byte> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<double> Xor(System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<short> Xor(System.Runtime.Intrinsics.Vector128<short> left, System.Runtime.Intrinsics.Vector128<short> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<uint> Xor(System.Runtime.Intrinsics.Vector128<uint> left, System.Runtime.Intrinsics.Vector128<uint> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<ulong> Xor(System.Runtime.Intrinsics.Vector128<ulong> left, System.Runtime.Intrinsics.Vector128<ulong> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<byte> Xor(System.Runtime.Intrinsics.Vector64<byte> left, System.Runtime.Intrinsics.Vector64<byte> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<double> Xor(System.Runtime.Intrinsics.Vector64<double> left, System.Runtime.Intrinsics.Vector64<double> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<short> Xor(System.Runtime.Intrinsics.Vector64<short> left, System.Runtime.Intrinsics.Vector64<short> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<int> Xor(System.Runtime.Intrinsics.Vector64<int> left, System.Runtime.Intrinsics.Vector64<int> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<long> Xor(System.Runtime.Intrinsics.Vector64<long> left, System.Runtime.Intrinsics.Vector64<long> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<sbyte> Xor(System.Runtime.Intrinsics.Vector64<sbyte> left, System.Runtime.Intrinsics.Vector64<sbyte> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<float> Xor(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<ushort> Xor(System.Runtime.Intrinsics.Vector64<ushort> left, System.Runtime.Intrinsics.Vector64<ushort> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<uint> Xor(System.Runtime.Intrinsics.Vector64<uint> left, System.Runtime.Intrinsics.Vector64<uint> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<ulong> Xor(System.Runtime.Intrinsics.Vector64<ulong> left, System.Runtime.Intrinsics.Vector64<ulong> right) { throw null; }
public new abstract partial class Arm64 : System.Runtime.Intrinsics.Arm.ArmBase.Arm64
{
internal Arm64() { }
public static System.Runtime.Intrinsics.Vector64<double> CompareTestScalar(System.Runtime.Intrinsics.Vector64<double> left, System.Runtime.Intrinsics.Vector64<double> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<long> CompareTestScalar(System.Runtime.Intrinsics.Vector64<long> left, System.Runtime.Intrinsics.Vector64<long> right) { throw null; }
public static System.Runtime.Intrinsics.Vector64<ulong> CompareTestScalar(System.Runtime.Intrinsics.Vector64<ulong> left, System.Runtime.Intrinsics.Vector64<ulong> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<double> Divide(System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<float> Divide(System.Runtime.Intrinsics.Vector128<float> left, System.Runtime.Intrinsics.Vector128<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<float> Divide(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<double> Max(System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<double> MaxScalar(System.Runtime.Intrinsics.Vector64<double> left, System.Runtime.Intrinsics.Vector64<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<float> MaxScalar(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<double> Min(System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<double> MinScalar(System.Runtime.Intrinsics.Vector64<double> left, System.Runtime.Intrinsics.Vector64<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<float> MinScalar(System.Runtime.Intrinsics.Vector64<float> left, System.Runtime.Intrinsics.Vector64<float> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<double> Multiply(System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<double> Negate(System.Runtime.Intrinsics.Vector128<double> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<long> Negate(System.Runtime.Intrinsics.Vector128<long> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<long> NegateScalar(System.Runtime.Intrinsics.Vector64<long> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<byte> ReverseElementBits(System.Runtime.Intrinsics.Vector128<byte> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<sbyte> ReverseElementBits(System.Runtime.Intrinsics.Vector128<sbyte> value) { throw null; }
public static System.Runtime.Intrinsics.Vector64<byte> ReverseElementBits(System.Runtime.Intrinsics.Vector64<byte> value) { throw null; }
public static System.Runtime.Intrinsics.Vector64<sbyte> ReverseElementBits(System.Runtime.Intrinsics.Vector64<sbyte> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<double> Sqrt(System.Runtime.Intrinsics.Vector128<double> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector128<float> Sqrt(System.Runtime.Intrinsics.Vector128<float> value) { throw null; }
+ public static System.Runtime.Intrinsics.Vector64<float> Sqrt(System.Runtime.Intrinsics.Vector64<float> value) { throw null; }
public static System.Runtime.Intrinsics.Vector128<double> Subtract(System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<byte> TransposeEven(System.Runtime.Intrinsics.Vector128<byte> left, System.Runtime.Intrinsics.Vector128<byte> right) { throw null; }
public static System.Runtime.Intrinsics.Vector128<double> TransposeEven(System.Runtime.Intrinsics.Vector128<double> left, System.Runtime.Intrinsics.Vector128<double> right) { throw null; }