--- /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.
+
+using System;
+using System.IO;
+
+// NOTE: This file isn't very robust and makes several assumptions.
+// It must be run such that its own directory is the working directory.
+
+private static readonly (string templateFileName, string[] templateData)[] Sse2Inputs = new []
+{
+ // TemplateName Isa, Method, BaseType, VectorType, VectorSize, NextValue, ValidateFirstResult, ValidateRemainingResults
+ ("SimpleBinOpTest.template", new string[] { "Sse2", "Add", "Double", "Vector128", "16", "(double)(random.NextDouble())", "BitConverter.DoubleToInt64Bits(left[0] + right[0]) != BitConverter.DoubleToInt64Bits(result[0])", "BitConverter.DoubleToInt64Bits(left[i] + right[i]) != BitConverter.DoubleToInt64Bits(result[i])"}),
+ ("SimpleBinOpTest.template", new string[] { "Sse2", "Add", "Byte", "Vector128", "16", "(byte)(random.Next(0, byte.MaxValue))", "(byte)(left[0] + right[0]) != result[0]", "(byte)(left[i] + right[i]) != result[i]"}),
+ ("SimpleBinOpTest.template", new string[] { "Sse2", "Add", "Int16", "Vector128", "16", "(short)(random.Next(short.MinValue, short.MaxValue))", "(short)(left[0] + right[0]) != result[0]", "(short)(left[i] + right[i]) != result[i]"}),
+ ("SimpleBinOpTest.template", new string[] { "Sse2", "Add", "Int32", "Vector128", "16", "(int)(random.Next(int.MinValue, int.MaxValue))", "(int)(left[0] + right[0]) != result[0]", "(int)(left[i] + right[i]) != result[i]"}),
+ ("SimpleBinOpTest.template", new string[] { "Sse2", "Add", "Int64", "Vector128", "16", "(long)(random.Next(int.MinValue, int.MaxValue))", "(long)(left[0] + right[0]) != result[0]", "(long)(left[i] + right[i]) != result[i]"}),
+ ("SimpleBinOpTest.template", new string[] { "Sse2", "Add", "SByte", "Vector128", "16", "(sbyte)(random.Next(sbyte.MinValue, sbyte.MaxValue))", "(sbyte)(left[0] + right[0]) != result[0]", "(sbyte)(left[i] + right[i]) != result[i]"}),
+ ("SimpleBinOpTest.template", new string[] { "Sse2", "Add", "UInt16", "Vector128", "16", "(ushort)(random.Next(0, ushort.MaxValue))", "(ushort)(left[0] + right[0]) != result[0]", "(ushort)(left[i] + right[i]) != result[i]"}),
+ ("SimpleBinOpTest.template", new string[] { "Sse2", "Add", "UInt32", "Vector128", "16", "(uint)(random.Next(0, int.MaxValue))", "(uint)(left[0] + right[0]) != result[0]", "(uint)(left[i] + right[i]) != result[i]"}),
+ ("SimpleBinOpTest.template", new string[] { "Sse2", "Add", "UInt64", "Vector128", "16", "(ulong)(random.Next(0, int.MaxValue))", "(ulong)(left[0] + right[0]) != result[0]", "(ulong)(left[i] + right[i]) != result[i]"}),
+};
+
+private static void ProcessInputs(string isa, (string templateFileName, string[] templateData)[] inputs)
+{
+ var testListFileName = Path.Combine("..", isa, $"Program.{isa}.cs");
+
+ using (var testListFile = new StreamWriter(testListFileName, append: false))
+ {
+ testListFile.WriteLine(@"// 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.
+
+using System;
+using System.Collections.Generic;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ static Program()
+ {
+ TestList = new Dictionary<string, Action>() {");
+
+ foreach (var input in inputs)
+ {
+ ProcessInput(testListFile, input);
+ }
+
+ testListFile.WriteLine(@" };
+ }
+ }
+}");
+ }
+}
+
+private static void ProcessInput(StreamWriter testListFile, (string templateFileName, string[] templateData) input)
+{
+ var testName = $"{input.templateData[1]}.{input.templateData[2]}";
+
+ // Ex: ["Add.Single"] = AddSingle
+ testListFile.WriteLine($@" [""{testName}""] = {input.templateData[1]}{input.templateData[2]},");
+
+ var testFileName = Path.Combine("..", input.templateData[0], $"{testName}.cs");
+ var template = File.ReadAllText(input.templateFileName);
+
+ if (input.templateData.Length != 0)
+ {
+ template = string.Format(template, input.templateData);
+ }
+
+ File.WriteAllText(testFileName, template);
+}
+
+ProcessInputs("Sse2", Sse2Inputs);
--- /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.
+
+using System;
+using System.Collections.Generic;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private const int PASS = 100;
+ private const int FAIL = 0;
+
+ private static readonly IDictionary<string, Action> TestList;
+
+ public static int Main(string[] args)
+ {
+ var isPassing = true;
+
+ foreach (string testToRun in GetTestsToRun(args))
+ {
+ Console.WriteLine($"Running {testToRun} test...");
+
+ try
+ {
+ TestList[testToRun].Invoke();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Error: {e.Message}");
+ isPassing = false;
+ }
+ }
+
+ return isPassing ? PASS : FAIL;
+ }
+
+ private static ICollection<string> GetTestsToRun(string[] args)
+ {
+ var testsToRun = new HashSet<string>();
+
+ for (var i = 0; i < args.Length; i++)
+ {
+ var testName = args[i].ToLowerInvariant();
+
+ if (testName == "all")
+ {
+ break;
+ }
+
+ if (!TestList.ContainsKey(testName))
+ {
+ PrintUsage();
+ }
+
+ testsToRun.Add(testName);
+ }
+
+ return (testsToRun.Count == 0) ? TestList.Keys : testsToRun;
+ }
+
+ private static void PrintUsage()
+ {
+ Console.WriteLine($@"Usage:
+{Environment.GetCommandLineArgs()[0]} [testName]
+
+ [testName]: The name of the function to test.
+ Defaults to 'all'.
+ Multiple can be specified.
+
+ Available Test Names:");
+ foreach (string testName in TestList.Keys)
+ {
+ Console.WriteLine($" {testName}");
+ }
+
+ Environment.Exit(FAIL);
+ }
+ }
+}
--- /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.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{{
+ public static partial class Program
+ {{
+ private static void {1}{2}()
+ {{
+ var test = new SimpleBinaryOpTest__{1}{2}();
+
+ if (test.IsSupported)
+ {{
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }}
+ 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__{1}{2}
+ {{
+ private const int VectorSize = {4};
+ private const int ElementCount = VectorSize / sizeof({2});
+
+ private static {2}[] _data1 = new {2}[ElementCount];
+ private static {2}[] _data2 = new {2}[ElementCount];
+
+ private static {3}<{2}> _clsVar1;
+ private static {3}<{2}> _clsVar2;
+
+ private {3}<{2}> _fld1;
+ private {3}<{2}> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<{2}> _dataTable;
+
+ static SimpleBinaryOpTest__{1}{2}()
+ {{
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) {{ _data1[i] = {5}; _data2[i] = {5}; }}
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{3}<{2}>, byte>(ref _clsVar1), ref Unsafe.As<{2}, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{3}<{2}>, byte>(ref _clsVar2), ref Unsafe.As<{2}, byte>(ref _data1[0]), VectorSize);
+ }}
+
+ public SimpleBinaryOpTest__{1}{2}()
+ {{
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) {{ _data1[i] = {5}; _data2[i] = {5}; }}
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{3}<{2}>, byte>(ref _fld1), ref Unsafe.As<{2}, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{3}<{2}>, byte>(ref _fld2), ref Unsafe.As<{2}, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) {{ _data1[i] = {5}; _data2[i] = {5}; }}
+ _dataTable = new SimpleBinaryOpTest__DataTable<{2}>(_data1, _data2, new {2}[ElementCount]);
+ }}
+
+ public bool IsSupported => {0}.IsSupported;
+
+ public bool Succeeded {{ get; set; }}
+
+ public void RunBasicScenario()
+ {{
+ var result = {0}.{1}(
+ Unsafe.Read<{3}<{2}>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<{3}<{2}>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }}
+
+ public void RunReflectionScenario()
+ {{
+ var result = typeof({0}).GetMethod(nameof({0}.{1}), new Type[] {{ typeof({3}<{2}>), typeof({3}<{2}>) }})
+ .Invoke(null, new object[] {{
+ Unsafe.Read<{3}<{2}>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<{3}<{2}>>(_dataTable.inArray2Ptr)
+ }});
+
+ Unsafe.Write(_dataTable.outArrayPtr, ({3}<{2}>)(result));
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }}
+
+ public void RunClsVarScenario()
+ {{
+ var result = {0}.{1}(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }}
+
+ public void RunLclVarScenario()
+ {{
+ var left = Unsafe.Read<{3}<{2}>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<{3}<{2}>>(_dataTable.inArray2Ptr);
+ var result = {0}.{1}(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }}
+
+ public void RunLclFldScenario()
+ {{
+ var test = new SimpleBinaryOpTest__{1}{2}();
+ var result = {0}.{1}(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }}
+
+ public void RunFldScenario()
+ {{
+ var result = {0}.{1}(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }}
+
+ public void RunUnsupportedScenario()
+ {{
+ Succeeded = false;
+
+ try
+ {{
+ RunBasicScenario();
+ }}
+ catch (PlatformNotSupportedException)
+ {{
+ Succeeded = true;
+ }}
+ }}
+
+ private void ValidateResult({3}<{2}> left, {3}<{2}> right, {2}[] result, [CallerMemberName] string method = "")
+ {{
+ {2}[] inArray1 = new {2}[ElementCount];
+ {2}[] inArray2 = new {2}[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }}
+
+ private void ValidateResult({2}[] left, {2}[] right, {2}[] result, [CallerMemberName] string method = "")
+ {{
+ if ({6})
+ {{
+ Succeeded = false;
+ }}
+ else
+ {{
+ for (var i = 1; i < left.Length; i++)
+ {{
+ if ({7})
+ {{
+ Succeeded = false;
+ break;
+ }}
+ }}
+ }}
+
+ if (!Succeeded)
+ {{
+ Console.WriteLine($"{{nameof({0})}}.{{nameof({0}.{1})}}<{2}>: {{method}} failed:");
+ Console.WriteLine($" left: ({{string.Join(", ", left)}})");
+ Console.WriteLine($" right: ({{string.Join(", ", right)}})");
+ Console.WriteLine($" result: ({{string.Join(", ", result)}})");
+ Console.WriteLine();
+ }}
+ }}
+ }}
+}}
--- /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.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public unsafe struct SimpleBinaryOpTest__DataTable<T> : IDisposable where T : struct
+ {
+ private GCHandle inHandle1;
+ private GCHandle inHandle2;
+ private GCHandle outHandle;
+
+ public T[] inArray1;
+ public T[] inArray2;
+ public T[] outArray;
+
+ public SimpleBinaryOpTest__DataTable(T[] inArray1, T[] inArray2, T[] outArray)
+ {
+ this.inArray1 = inArray1;
+ this.inArray2 = inArray2;
+ this.outArray = outArray;
+
+ this.inHandle1 = GCHandle.Alloc(inArray1, GCHandleType.Pinned);
+ this.inHandle2 = GCHandle.Alloc(inArray2, GCHandleType.Pinned);
+ this.outHandle = GCHandle.Alloc(outArray, GCHandleType.Pinned);
+ }
+
+ public void* inArray1Ptr => inHandle1.AddrOfPinnedObject().ToPointer();
+ public void* inArray2Ptr => inHandle2.AddrOfPinnedObject().ToPointer();
+ public void* outArrayPtr => outHandle.AddrOfPinnedObject().ToPointer();
+
+ public void Dispose()
+ {
+ inHandle1.Free();
+ inHandle2.Free();
+ outHandle.Free();
+ }
+ }
+}
--- /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.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void AddByte()
+ {
+ var test = new SimpleBinaryOpTest__AddByte();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ 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__AddByte
+ {
+ private const int VectorSize = 16;
+ private const int ElementCount = VectorSize / sizeof(Byte);
+
+ private static Byte[] _data1 = new Byte[ElementCount];
+ private static Byte[] _data2 = new Byte[ElementCount];
+
+ private static Vector128<Byte> _clsVar1;
+ private static Vector128<Byte> _clsVar2;
+
+ private Vector128<Byte> _fld1;
+ private Vector128<Byte> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<Byte> _dataTable;
+
+ static SimpleBinaryOpTest__AddByte()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (byte)(random.Next(0, byte.MaxValue)); _data2[i] = (byte)(random.Next(0, byte.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar1), ref Unsafe.As<Byte, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar2), ref Unsafe.As<Byte, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__AddByte()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (byte)(random.Next(0, byte.MaxValue)); _data2[i] = (byte)(random.Next(0, byte.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld1), ref Unsafe.As<Byte, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld2), ref Unsafe.As<Byte, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (byte)(random.Next(0, byte.MaxValue)); _data2[i] = (byte)(random.Next(0, byte.MaxValue)); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<Byte>(_data1, _data2, new Byte[ElementCount]);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Sse2.Add(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Add), 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.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Add(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector128<Byte>>(_dataTable.inArray2Ptr);
+ var result = Sse2.Add(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__AddByte();
+ var result = Sse2.Add(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Add(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Byte> left, Vector128<Byte> right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray1 = new Byte[ElementCount];
+ Byte[] inArray2 = new Byte[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }
+
+ private void ValidateResult(Byte[] left, Byte[] right, Byte[] result, [CallerMemberName] string method = "")
+ {
+ if ((byte)(left[0] + right[0]) != result[0])
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if ((byte)(left[i] + right[i]) != result[i])
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Add)}<Byte>: {method} failed:");
+ Console.WriteLine($" left: ({string.Join(", ", left)})");
+ Console.WriteLine($" right: ({string.Join(", ", right)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
--- /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.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void AddDouble()
+ {
+ var test = new SimpleBinaryOpTest__AddDouble();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ 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__AddDouble
+ {
+ private const int VectorSize = 16;
+ private const int ElementCount = VectorSize / sizeof(Double);
+
+ private static Double[] _data1 = new Double[ElementCount];
+ private static Double[] _data2 = new Double[ElementCount];
+
+ private static Vector128<Double> _clsVar1;
+ private static Vector128<Double> _clsVar2;
+
+ private Vector128<Double> _fld1;
+ private Vector128<Double> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<Double> _dataTable;
+
+ static SimpleBinaryOpTest__AddDouble()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__AddDouble()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); _data2[i] = (double)(random.NextDouble()); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<Double>(_data1, _data2, new Double[ElementCount]);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Sse2.Add(
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Add), 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.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Add(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
+ var result = Sse2.Add(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__AddDouble();
+ var result = Sse2.Add(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Add(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Double> left, Vector128<Double> right, Double[] result, [CallerMemberName] string method = "")
+ {
+ Double[] inArray1 = new Double[ElementCount];
+ Double[] inArray2 = new Double[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }
+
+ private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
+ {
+ if (BitConverter.DoubleToInt64Bits(left[0] + right[0]) != BitConverter.DoubleToInt64Bits(result[0]))
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if (BitConverter.DoubleToInt64Bits(left[i] + right[i]) != BitConverter.DoubleToInt64Bits(result[i]))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Add)}<Double>: {method} failed:");
+ Console.WriteLine($" left: ({string.Join(", ", left)})");
+ Console.WriteLine($" right: ({string.Join(", ", right)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
--- /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.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void AddInt16()
+ {
+ var test = new SimpleBinaryOpTest__AddInt16();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ 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__AddInt16
+ {
+ private const int VectorSize = 16;
+ private const int ElementCount = VectorSize / sizeof(Int16);
+
+ private static Int16[] _data1 = new Int16[ElementCount];
+ private static Int16[] _data2 = new Int16[ElementCount];
+
+ private static Vector128<Int16> _clsVar1;
+ private static Vector128<Int16> _clsVar2;
+
+ private Vector128<Int16> _fld1;
+ private Vector128<Int16> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<Int16> _dataTable;
+
+ static SimpleBinaryOpTest__AddInt16()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (short)(random.Next(short.MinValue, short.MaxValue)); _data2[i] = (short)(random.Next(short.MinValue, short.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar1), ref Unsafe.As<Int16, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar2), ref Unsafe.As<Int16, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__AddInt16()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (short)(random.Next(short.MinValue, short.MaxValue)); _data2[i] = (short)(random.Next(short.MinValue, short.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld1), ref Unsafe.As<Int16, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld2), ref Unsafe.As<Int16, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (short)(random.Next(short.MinValue, short.MaxValue)); _data2[i] = (short)(random.Next(short.MinValue, short.MaxValue)); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<Int16>(_data1, _data2, new Int16[ElementCount]);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Sse2.Add(
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Add), 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.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Add(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector128<Int16>>(_dataTable.inArray2Ptr);
+ var result = Sse2.Add(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__AddInt16();
+ var result = Sse2.Add(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Add(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int16> left, Vector128<Int16> right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray1 = new Int16[ElementCount];
+ Int16[] inArray2 = new Int16[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }
+
+ private void ValidateResult(Int16[] left, Int16[] right, Int16[] result, [CallerMemberName] string method = "")
+ {
+ if ((short)(left[0] + right[0]) != result[0])
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if ((short)(left[i] + right[i]) != result[i])
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Add)}<Int16>: {method} failed:");
+ Console.WriteLine($" left: ({string.Join(", ", left)})");
+ Console.WriteLine($" right: ({string.Join(", ", right)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
--- /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.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void AddInt32()
+ {
+ var test = new SimpleBinaryOpTest__AddInt32();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ 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__AddInt32
+ {
+ private const int VectorSize = 16;
+ private const int ElementCount = VectorSize / sizeof(Int32);
+
+ private static Int32[] _data1 = new Int32[ElementCount];
+ private static Int32[] _data2 = new Int32[ElementCount];
+
+ private static Vector128<Int32> _clsVar1;
+ private static Vector128<Int32> _clsVar2;
+
+ private Vector128<Int32> _fld1;
+ private Vector128<Int32> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<Int32> _dataTable;
+
+ static SimpleBinaryOpTest__AddInt32()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (int)(random.Next(int.MinValue, int.MaxValue)); _data2[i] = (int)(random.Next(int.MinValue, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar1), ref Unsafe.As<Int32, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar2), ref Unsafe.As<Int32, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__AddInt32()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (int)(random.Next(int.MinValue, int.MaxValue)); _data2[i] = (int)(random.Next(int.MinValue, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld1), ref Unsafe.As<Int32, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld2), ref Unsafe.As<Int32, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (int)(random.Next(int.MinValue, int.MaxValue)); _data2[i] = (int)(random.Next(int.MinValue, int.MaxValue)); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<Int32>(_data1, _data2, new Int32[ElementCount]);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Sse2.Add(
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Add), 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.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Add(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector128<Int32>>(_dataTable.inArray2Ptr);
+ var result = Sse2.Add(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__AddInt32();
+ var result = Sse2.Add(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Add(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int32> left, Vector128<Int32> right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray1 = new Int32[ElementCount];
+ Int32[] inArray2 = new Int32[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }
+
+ private void ValidateResult(Int32[] left, Int32[] right, Int32[] result, [CallerMemberName] string method = "")
+ {
+ if ((int)(left[0] + right[0]) != result[0])
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if ((int)(left[i] + right[i]) != result[i])
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Add)}<Int32>: {method} failed:");
+ Console.WriteLine($" left: ({string.Join(", ", left)})");
+ Console.WriteLine($" right: ({string.Join(", ", right)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
--- /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.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void AddInt64()
+ {
+ var test = new SimpleBinaryOpTest__AddInt64();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ 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__AddInt64
+ {
+ private const int VectorSize = 16;
+ private const int ElementCount = VectorSize / sizeof(Int64);
+
+ private static Int64[] _data1 = new Int64[ElementCount];
+ private static Int64[] _data2 = new Int64[ElementCount];
+
+ private static Vector128<Int64> _clsVar1;
+ private static Vector128<Int64> _clsVar2;
+
+ private Vector128<Int64> _fld1;
+ private Vector128<Int64> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<Int64> _dataTable;
+
+ static SimpleBinaryOpTest__AddInt64()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (long)(random.Next(int.MinValue, int.MaxValue)); _data2[i] = (long)(random.Next(int.MinValue, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar1), ref Unsafe.As<Int64, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar2), ref Unsafe.As<Int64, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__AddInt64()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (long)(random.Next(int.MinValue, int.MaxValue)); _data2[i] = (long)(random.Next(int.MinValue, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld1), ref Unsafe.As<Int64, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld2), ref Unsafe.As<Int64, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (long)(random.Next(int.MinValue, int.MaxValue)); _data2[i] = (long)(random.Next(int.MinValue, int.MaxValue)); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<Int64>(_data1, _data2, new Int64[ElementCount]);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Sse2.Add(
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Add), 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.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Add(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector128<Int64>>(_dataTable.inArray2Ptr);
+ var result = Sse2.Add(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__AddInt64();
+ var result = Sse2.Add(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Add(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int64> left, Vector128<Int64> right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray1 = new Int64[ElementCount];
+ Int64[] inArray2 = new Int64[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }
+
+ private void ValidateResult(Int64[] left, Int64[] right, Int64[] result, [CallerMemberName] string method = "")
+ {
+ if ((long)(left[0] + right[0]) != result[0])
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if ((long)(left[i] + right[i]) != result[i])
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Add)}<Int64>: {method} failed:");
+ Console.WriteLine($" left: ({string.Join(", ", left)})");
+ Console.WriteLine($" right: ({string.Join(", ", right)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
--- /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.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void AddSByte()
+ {
+ var test = new SimpleBinaryOpTest__AddSByte();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ 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__AddSByte
+ {
+ private const int VectorSize = 16;
+ private const int ElementCount = VectorSize / sizeof(SByte);
+
+ private static SByte[] _data1 = new SByte[ElementCount];
+ private static SByte[] _data2 = new SByte[ElementCount];
+
+ private static Vector128<SByte> _clsVar1;
+ private static Vector128<SByte> _clsVar2;
+
+ private Vector128<SByte> _fld1;
+ private Vector128<SByte> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<SByte> _dataTable;
+
+ static SimpleBinaryOpTest__AddSByte()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (sbyte)(random.Next(sbyte.MinValue, sbyte.MaxValue)); _data2[i] = (sbyte)(random.Next(sbyte.MinValue, sbyte.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar1), ref Unsafe.As<SByte, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar2), ref Unsafe.As<SByte, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__AddSByte()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (sbyte)(random.Next(sbyte.MinValue, sbyte.MaxValue)); _data2[i] = (sbyte)(random.Next(sbyte.MinValue, sbyte.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld1), ref Unsafe.As<SByte, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld2), ref Unsafe.As<SByte, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (sbyte)(random.Next(sbyte.MinValue, sbyte.MaxValue)); _data2[i] = (sbyte)(random.Next(sbyte.MinValue, sbyte.MaxValue)); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<SByte>(_data1, _data2, new SByte[ElementCount]);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Sse2.Add(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Add), 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.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Add(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector128<SByte>>(_dataTable.inArray2Ptr);
+ var result = Sse2.Add(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__AddSByte();
+ var result = Sse2.Add(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Add(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<SByte> left, Vector128<SByte> right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray1 = new SByte[ElementCount];
+ SByte[] inArray2 = new SByte[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }
+
+ private void ValidateResult(SByte[] left, SByte[] right, SByte[] result, [CallerMemberName] string method = "")
+ {
+ if ((sbyte)(left[0] + right[0]) != result[0])
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if ((sbyte)(left[i] + right[i]) != result[i])
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Add)}<SByte>: {method} failed:");
+ Console.WriteLine($" left: ({string.Join(", ", left)})");
+ Console.WriteLine($" right: ({string.Join(", ", right)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
--- /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.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void AddUInt16()
+ {
+ var test = new SimpleBinaryOpTest__AddUInt16();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ 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__AddUInt16
+ {
+ private const int VectorSize = 16;
+ private const int ElementCount = VectorSize / sizeof(UInt16);
+
+ private static UInt16[] _data1 = new UInt16[ElementCount];
+ private static UInt16[] _data2 = new UInt16[ElementCount];
+
+ private static Vector128<UInt16> _clsVar1;
+ private static Vector128<UInt16> _clsVar2;
+
+ private Vector128<UInt16> _fld1;
+ private Vector128<UInt16> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<UInt16> _dataTable;
+
+ static SimpleBinaryOpTest__AddUInt16()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (ushort)(random.Next(0, ushort.MaxValue)); _data2[i] = (ushort)(random.Next(0, ushort.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar1), ref Unsafe.As<UInt16, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar2), ref Unsafe.As<UInt16, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__AddUInt16()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (ushort)(random.Next(0, ushort.MaxValue)); _data2[i] = (ushort)(random.Next(0, ushort.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld1), ref Unsafe.As<UInt16, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld2), ref Unsafe.As<UInt16, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (ushort)(random.Next(0, ushort.MaxValue)); _data2[i] = (ushort)(random.Next(0, ushort.MaxValue)); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<UInt16>(_data1, _data2, new UInt16[ElementCount]);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Sse2.Add(
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Add), 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.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Add(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArray2Ptr);
+ var result = Sse2.Add(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__AddUInt16();
+ var result = Sse2.Add(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Add(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt16> left, Vector128<UInt16> right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray1 = new UInt16[ElementCount];
+ UInt16[] inArray2 = new UInt16[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }
+
+ private void ValidateResult(UInt16[] left, UInt16[] right, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ if ((ushort)(left[0] + right[0]) != result[0])
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if ((ushort)(left[i] + right[i]) != result[i])
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Add)}<UInt16>: {method} failed:");
+ Console.WriteLine($" left: ({string.Join(", ", left)})");
+ Console.WriteLine($" right: ({string.Join(", ", right)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
--- /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.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void AddUInt32()
+ {
+ var test = new SimpleBinaryOpTest__AddUInt32();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ 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__AddUInt32
+ {
+ private const int VectorSize = 16;
+ private const int ElementCount = VectorSize / sizeof(UInt32);
+
+ private static UInt32[] _data1 = new UInt32[ElementCount];
+ private static UInt32[] _data2 = new UInt32[ElementCount];
+
+ private static Vector128<UInt32> _clsVar1;
+ private static Vector128<UInt32> _clsVar2;
+
+ private Vector128<UInt32> _fld1;
+ private Vector128<UInt32> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<UInt32> _dataTable;
+
+ static SimpleBinaryOpTest__AddUInt32()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (uint)(random.Next(0, int.MaxValue)); _data2[i] = (uint)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar1), ref Unsafe.As<UInt32, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar2), ref Unsafe.As<UInt32, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__AddUInt32()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (uint)(random.Next(0, int.MaxValue)); _data2[i] = (uint)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld1), ref Unsafe.As<UInt32, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld2), ref Unsafe.As<UInt32, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (uint)(random.Next(0, int.MaxValue)); _data2[i] = (uint)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<UInt32>(_data1, _data2, new UInt32[ElementCount]);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Sse2.Add(
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Add), 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.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Add(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArray2Ptr);
+ var result = Sse2.Add(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__AddUInt32();
+ var result = Sse2.Add(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Add(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt32> left, Vector128<UInt32> right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray1 = new UInt32[ElementCount];
+ UInt32[] inArray2 = new UInt32[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }
+
+ private void ValidateResult(UInt32[] left, UInt32[] right, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ if ((uint)(left[0] + right[0]) != result[0])
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if ((uint)(left[i] + right[i]) != result[i])
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Add)}<UInt32>: {method} failed:");
+ Console.WriteLine($" left: ({string.Join(", ", left)})");
+ Console.WriteLine($" right: ({string.Join(", ", right)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
--- /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.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ private static void AddUInt64()
+ {
+ var test = new SimpleBinaryOpTest__AddUInt64();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works
+ test.RunBasicScenario();
+
+ // Validates calling via reflection works
+ test.RunReflectionScenario();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works
+ test.RunLclVarScenario();
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ 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__AddUInt64
+ {
+ private const int VectorSize = 16;
+ private const int ElementCount = VectorSize / sizeof(UInt64);
+
+ private static UInt64[] _data1 = new UInt64[ElementCount];
+ private static UInt64[] _data2 = new UInt64[ElementCount];
+
+ private static Vector128<UInt64> _clsVar1;
+ private static Vector128<UInt64> _clsVar2;
+
+ private Vector128<UInt64> _fld1;
+ private Vector128<UInt64> _fld2;
+
+ private SimpleBinaryOpTest__DataTable<UInt64> _dataTable;
+
+ static SimpleBinaryOpTest__AddUInt64()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (ulong)(random.Next(0, int.MaxValue)); _data2[i] = (ulong)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar1), ref Unsafe.As<UInt64, byte>(ref _data2[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar2), ref Unsafe.As<UInt64, byte>(ref _data1[0]), VectorSize);
+ }
+
+ public SimpleBinaryOpTest__AddUInt64()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (ulong)(random.Next(0, int.MaxValue)); _data2[i] = (ulong)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld1), ref Unsafe.As<UInt64, byte>(ref _data1[0]), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld2), ref Unsafe.As<UInt64, byte>(ref _data2[0]), VectorSize);
+
+ for (var i = 0; i < ElementCount; i++) { _data1[i] = (ulong)(random.Next(0, int.MaxValue)); _data2[i] = (ulong)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleBinaryOpTest__DataTable<UInt64>(_data1, _data2, new UInt64[ElementCount]);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario()
+ {
+ var result = Sse2.Add(
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr),
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr)
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunReflectionScenario()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Add), 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.inArray1, _dataTable.inArray2, _dataTable.outArray);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Add(
+ _clsVar1,
+ _clsVar2
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar1, _clsVar2, _dataTable.outArray);
+ }
+
+ public void RunLclVarScenario()
+ {
+ var left = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray1Ptr);
+ var right = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArray2Ptr);
+ var result = Sse2.Add(left, right);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(left, right, _dataTable.outArray);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleBinaryOpTest__AddUInt64();
+ var result = Sse2.Add(test._fld1, test._fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld1, test._fld2, _dataTable.outArray);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Add(_fld1, _fld2);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld1, _fld2, _dataTable.outArray);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt64> left, Vector128<UInt64> right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray1 = new UInt64[ElementCount];
+ UInt64[] inArray2 = new UInt64[ElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray1[0]), left);
+ Unsafe.Write(Unsafe.AsPointer(ref inArray2[0]), right);
+
+ ValidateResult(inArray1, inArray2, result, method);
+ }
+
+ private void ValidateResult(UInt64[] left, UInt64[] right, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ if ((ulong)(left[0] + right[0]) != result[0])
+ {
+ Succeeded = false;
+ }
+ else
+ {
+ for (var i = 1; i < left.Length; i++)
+ {
+ if ((ulong)(left[i] + right[i]) != result[i])
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Add)}<UInt64>: {method} failed:");
+ Console.WriteLine($" left: ({string.Join(", ", left)})");
+ Console.WriteLine($" right: ({string.Join(", ", right)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
+++ /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.
-//
-
-using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics.X86;
-using System.Runtime.Intrinsics;
-
-namespace IntelHardwareIntrinsicTest
-{
- class Program
- {
- const int Pass = 100;
- const int Fail = 0;
-
- static unsafe int Main(string[] args)
- {
- int testResult = Pass;
-
- if (Sse2.IsSupported)
- {
- using (TestTable<double> doubleTable = new TestTable<double>(new double[2] { 1, -5 }, new double[2] { 22, -1 }, new double[2]))
- using (TestTable<int> intTable = new TestTable<int>(new int[4] { 1, -5, 100, 0 }, new int[4] { 22, -1, -50, 0 }, new int[4]))
- using (TestTable<long> longTable = new TestTable<long>(new long[2] { 1, -5 }, new long[2] { 22, -1 }, new long[2]))
- using (TestTable<uint> uintTable = new TestTable<uint>(new uint[4] { 1, 5, 100, 0 }, new uint[4] { 22, 1, 50, 0 }, new uint[4]))
- using (TestTable<ulong> ulongTable = new TestTable<ulong>(new ulong[2] { 1, 5 }, new ulong[2] { 22, 1 }, new ulong[2]))
- using (TestTable<short> shortTable = new TestTable<short>(new short[8] { 1, -5, 100, 0, 1, -5, 100, 0 }, new short[8] { 22, -1, -50, 0, 22, -1, -50, 0 }, new short[8]))
- using (TestTable<ushort> ushortTable = new TestTable<ushort>(new ushort[8] { 1, 5, 100, 0, 1, 5, 100, 0 }, new ushort[8] { 22, 1, 50, 0, 22, 1, 50, 0 }, new ushort[8]))
- using (TestTable<sbyte> sbyteTable = new TestTable<sbyte>(new sbyte[16] { 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0, 1, -5, 100, 0 }, new sbyte[16] { 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0, 22, -1, -50, 0 }, new sbyte[16]))
- using (TestTable<byte> byteTable = new TestTable<byte>(new byte[16] { 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0, 1, 5, 100, 0 }, new byte[16] { 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0, 22, 1, 50, 0 }, new byte[16]))
- {
- var vd1 = Unsafe.Read<Vector128<double>>(doubleTable.inArray1Ptr);
- var vd2 = Unsafe.Read<Vector128<double>>(doubleTable.inArray2Ptr);
- var vd3 = Sse2.Add(vd1, vd2);
- Unsafe.Write(doubleTable.outArrayPtr, vd3);
-
- if (!doubleTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed on double:");
- foreach (var item in doubleTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- vd3 = (Vector128<double>)typeof(Sse2).GetMethod(nameof(Sse2.Add), new Type[] { vd1.GetType(), vd2.GetType() }).Invoke(null, new object[] { vd1, vd2 });
- Unsafe.Write(doubleTable.outArrayPtr, vd3);
-
- if (!doubleTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed via reflection on double:");
- foreach (var item in doubleTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- var vi1 = Unsafe.Read<Vector128<int>>(intTable.inArray1Ptr);
- var vi2 = Unsafe.Read<Vector128<int>>(intTable.inArray2Ptr);
- var vi3 = Sse2.Add(vi1, vi2);
- Unsafe.Write(intTable.outArrayPtr, vi3);
-
- if (!intTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed on int:");
- foreach (var item in intTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- vi3 = (Vector128<int>)typeof(Sse2).GetMethod(nameof(Sse2.Add), new Type[] { vi1.GetType(), vi2.GetType() }).Invoke(null, new object[] { vi1, vi2 });
- Unsafe.Write(intTable.outArrayPtr, vi3);
-
- if (!intTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed via reflection on int:");
- foreach (var item in intTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- var vl1 = Unsafe.Read<Vector128<long>>(longTable.inArray1Ptr);
- var vl2 = Unsafe.Read<Vector128<long>>(longTable.inArray2Ptr);
- var vl3 = Sse2.Add(vl1, vl2);
- Unsafe.Write(longTable.outArrayPtr, vl3);
-
- if (!longTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed on long:");
- foreach (var item in longTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- vl3 = (Vector128<long>)typeof(Sse2).GetMethod(nameof(Sse2.Add), new Type[] { vl1.GetType(), vl2.GetType() }).Invoke(null, new object[] { vl1, vl2 });
- Unsafe.Write(longTable.outArrayPtr, vl3);
-
- if (!longTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed via reflection on long:");
- foreach (var item in longTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- var vui1 = Unsafe.Read<Vector128<uint>>(uintTable.inArray1Ptr);
- var vui2 = Unsafe.Read<Vector128<uint>>(uintTable.inArray2Ptr);
- var vui3 = Sse2.Add(vui1, vui2);
- Unsafe.Write(uintTable.outArrayPtr, vui3);
-
- if (!uintTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed on uint:");
- foreach (var item in uintTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- vui3 = (Vector128<uint>)typeof(Sse2).GetMethod(nameof(Sse2.Add), new Type[] { vui1.GetType(), vui2.GetType() }).Invoke(null, new object[] { vui1, vui2 });
- Unsafe.Write(uintTable.outArrayPtr, vui3);
-
- if (!uintTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed via reflection on uint:");
- foreach (var item in uintTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- var vul1 = Unsafe.Read<Vector128<ulong>>(ulongTable.inArray1Ptr);
- var vul2 = Unsafe.Read<Vector128<ulong>>(ulongTable.inArray2Ptr);
- var vul3 = Sse2.Add(vul1, vul2);
- Unsafe.Write(ulongTable.outArrayPtr, vul3);
-
- if (!ulongTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed on ulong:");
- foreach (var item in ulongTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- vul3 = (Vector128<ulong>)typeof(Sse2).GetMethod(nameof(Sse2.Add), new Type[] { vul1.GetType(), vul2.GetType() }).Invoke(null, new object[] { vul1, vul2 });
- Unsafe.Write(ulongTable.outArrayPtr, vul3);
-
- if (!ulongTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed via reflection on ulong:");
- foreach (var item in ulongTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- var vs1 = Unsafe.Read<Vector128<short>>(shortTable.inArray1Ptr);
- var vs2 = Unsafe.Read<Vector128<short>>(shortTable.inArray2Ptr);
- var vs3 = Sse2.Add(vs1, vs2);
- Unsafe.Write(shortTable.outArrayPtr, vs3);
-
- if (!shortTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed on short:");
- foreach (var item in shortTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- vs3 = (Vector128<short>)typeof(Sse2).GetMethod(nameof(Sse2.Add), new Type[] { vs1.GetType(), vs2.GetType() }).Invoke(null, new object[] { vs1, vs2 });
- Unsafe.Write(shortTable.outArrayPtr, vs3);
-
- if (!shortTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed via reflection on short:");
- foreach (var item in shortTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- var vus1 = Unsafe.Read<Vector128<ushort>>(ushortTable.inArray1Ptr);
- var vus2 = Unsafe.Read<Vector128<ushort>>(ushortTable.inArray2Ptr);
- var vus3 = Sse2.Add(vus1, vus2);
- Unsafe.Write(ushortTable.outArrayPtr, vus3);
-
- if (!ushortTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed on ushort:");
- foreach (var item in ushortTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- vus3 = (Vector128<ushort>)typeof(Sse2).GetMethod(nameof(Sse2.Add), new Type[] { vus1.GetType(), vus2.GetType() }).Invoke(null, new object[] { vus1, vus2 });
- Unsafe.Write(ushortTable.outArrayPtr, vus3);
-
- if (!ushortTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed via reflection on ushort:");
- foreach (var item in ushortTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- var vsb1 = Unsafe.Read<Vector128<sbyte>>(sbyteTable.inArray1Ptr);
- var vsb2 = Unsafe.Read<Vector128<sbyte>>(sbyteTable.inArray2Ptr);
- var vsb3 = Sse2.Add(vsb1, vsb2);
- Unsafe.Write(sbyteTable.outArrayPtr, vsb3);
-
- if (!sbyteTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed on sbyte:");
- foreach (var item in sbyteTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- vsb3 = (Vector128<sbyte>)typeof(Sse2).GetMethod(nameof(Sse2.Add), new Type[] { vsb1.GetType(), vsb2.GetType() }).Invoke(null, new object[] { vsb1, vsb2 });
- Unsafe.Write(sbyteTable.outArrayPtr, vsb3);
-
- if (!sbyteTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed via reflection on sbyte:");
- foreach (var item in sbyteTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- var vb1 = Unsafe.Read<Vector128<byte>>(byteTable.inArray1Ptr);
- var vb2 = Unsafe.Read<Vector128<byte>>(byteTable.inArray2Ptr);
- var vb3 = Sse2.Add(vb1, vb2);
- Unsafe.Write(byteTable.outArrayPtr, vb3);
-
- if (!byteTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed on byte:");
- foreach (var item in byteTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- vb3 = (Vector128<byte>)typeof(Sse2).GetMethod(nameof(Sse2.Add), new Type[] { vb1.GetType(), vb2.GetType() }).Invoke(null, new object[] { vb1, vb2 });
- Unsafe.Write(byteTable.outArrayPtr, vb3);
-
- if (!byteTable.CheckResult((x, y, z) => x + y == z))
- {
- Console.WriteLine("SSE2 Add failed via reflection on byte:");
- foreach (var item in byteTable.outArray)
- {
- Console.Write(item + ", ");
- }
- Console.WriteLine();
- testResult = Fail;
- }
-
- }
- }
-
-
- return testResult;
- }
-
- public unsafe struct TestTable<T> : IDisposable where T : struct
- {
- public T[] inArray1;
- public T[] inArray2;
- public T[] outArray;
-
- public void* inArray1Ptr => inHandle1.AddrOfPinnedObject().ToPointer();
- public void* inArray2Ptr => inHandle2.AddrOfPinnedObject().ToPointer();
- public void* outArrayPtr => outHandle.AddrOfPinnedObject().ToPointer();
-
- GCHandle inHandle1;
- GCHandle inHandle2;
- GCHandle outHandle;
- public TestTable(T[] a, T[] b, T[] c)
- {
- this.inArray1 = a;
- this.inArray2 = b;
- this.outArray = c;
-
- inHandle1 = GCHandle.Alloc(inArray1, GCHandleType.Pinned);
- inHandle2 = GCHandle.Alloc(inArray2, GCHandleType.Pinned);
- outHandle = GCHandle.Alloc(outArray, GCHandleType.Pinned);
- }
- public bool CheckResult(Func<T, T, T, bool> check)
- {
- for (int i = 0; i < inArray1.Length; i++)
- {
- if (!check(inArray1[i], inArray2[i], outArray[i]))
- {
- return false;
- }
- }
- return true;
- }
-
- public void Dispose()
- {
- inHandle1.Free();
- inHandle2.Free();
- outHandle.Free();
- }
- }
-
- }
-}
--- /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.
+
+using System;
+using System.Collections.Generic;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+ public static partial class Program
+ {
+ static Program()
+ {
+ TestList = new Dictionary<string, Action>() {
+ ["Add.Double"] = AddDouble,
+ ["Add.Byte"] = AddByte,
+ ["Add.Int16"] = AddInt16,
+ ["Add.Int32"] = AddInt32,
+ ["Add.Int64"] = AddInt64,
+ ["Add.SByte"] = AddSByte,
+ ["Add.UInt16"] = AddUInt16,
+ ["Add.UInt32"] = AddUInt32,
+ ["Add.UInt64"] = AddUInt64,
+ };
+ }
+ }
+}
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
- <Compile Include="Add.cs" />
+ <Compile Include="Add.Byte.cs" />
+ <Compile Include="Add.Double.cs" />
+ <Compile Include="Add.Int16.cs" />
+ <Compile Include="Add.Int32.cs" />
+ <Compile Include="Add.Int64.cs" />
+ <Compile Include="Add.SByte.cs" />
+ <Compile Include="Add.UInt16.cs" />
+ <Compile Include="Add.UInt32.cs" />
+ <Compile Include="Add.UInt64.cs" />
+ <Compile Include="Program.Sse2.cs" />
+ <Compile Include="..\Shared\Program.cs" />
+ <Compile Include="..\Shared\SimpleBinOpTest_DataTable.cs" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
<PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
- <Compile Include="Add.cs" />
+ <Compile Include="Add.Byte.cs" />
+ <Compile Include="Add.Double.cs" />
+ <Compile Include="Add.Int16.cs" />
+ <Compile Include="Add.Int32.cs" />
+ <Compile Include="Add.Int64.cs" />
+ <Compile Include="Add.SByte.cs" />
+ <Compile Include="Add.UInt16.cs" />
+ <Compile Include="Add.UInt32.cs" />
+ <Compile Include="Add.UInt64.cs" />
+ <Compile Include="Program.Sse2.cs" />
+ <Compile Include="..\Shared\Program.cs" />
+ <Compile Include="..\Shared\SimpleBinOpTest_DataTable.cs" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
<PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>