Ensure that we check for implicit ivals for single argument intrinsics before the...
authorTanner Gooding <tagoo@outlook.com>
Wed, 7 Aug 2019 16:15:29 +0000 (09:15 -0700)
committerWilliam Godbe <wigodbe@microsoft.com>
Wed, 7 Aug 2019 16:15:29 +0000 (09:15 -0700)
* Ensure that we check for implicit ivals for single argument intrinsics before the SIMDScalar handling.

* Adding test template entries for the unary overloads of the Sse41.Round functions

* Regenerating the hardware intrinsic test templates.

13 files changed:
src/jit/hwintrinsiccodegenxarch.cpp
tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx
tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/Program.Sse41_Overloaded.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundCurrentDirectionScalar.Double.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundCurrentDirectionScalar.Single.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToNearestIntegerScalar.Double.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToNearestIntegerScalar.Single.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToNegativeInfinityScalar.Double.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToNegativeInfinityScalar.Single.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToPositiveInfinityScalar.Double.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToPositiveInfinityScalar.Single.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/Sse41_Overloaded_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/Sse41_Overloaded_ro.csproj [new file with mode: 0644]

index a12fa1d..42dba82 100644 (file)
@@ -122,15 +122,15 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
                     genConsumeRegs(op1);
                     op1Reg = op1->gtRegNum;
 
-                    if ((category == HW_Category_SIMDScalar) && HWIntrinsicInfo::CopiesUpperBits(intrinsicId))
-                    {
-                        emit->emitIns_SIMD_R_R_R(ins, simdSize, targetReg, op1Reg, op1Reg);
-                    }
-                    else if ((ival != -1) && varTypeIsFloating(baseType))
+                    if ((ival != -1) && varTypeIsFloating(baseType))
                     {
                         assert((ival >= 0) && (ival <= 127));
                         genHWIntrinsic_R_RM_I(node, ins, (int8_t)ival);
                     }
+                    else if ((category == HW_Category_SIMDScalar) && HWIntrinsicInfo::CopiesUpperBits(intrinsicId))
+                    {
+                        emit->emitIns_SIMD_R_R_R(ins, simdSize, targetReg, op1Reg, op1Reg);
+                    }
                     else
                     {
                         genHWIntrinsic_R_RM(node, ins, simdSize);
index 853681c..174d4e5 100644 (file)
@@ -598,6 +598,18 @@ private static readonly (string templateFileName, Dictionary<string, string> tem
     ("BooleanBinOpTest.template",    new Dictionary<string, string> { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "TestZ",                         ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt64",  ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "UInt64", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt64",                                                                                                      ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()",                                                             ["ValidateFirstResult"] = "(left[i] & right[i]) == 0"}),
 };
 
+private static readonly (string templateFileName, Dictionary<string, string> templateData)[] Sse41_OverloadedInputs = new []
+{
+    ("SimpleUnOpTest.template",      new Dictionary<string, string> { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "RoundCurrentDirectionScalar",   ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double",  ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Double",                                                                                                                                                                   ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()",                                                                                                                     ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Round(firstOp[0]))",                                                                                                                                                  ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i])"}),
+    ("SimpleUnOpTest.template",      new Dictionary<string, string> { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse",  ["Method"] = "RoundCurrentDirectionScalar",   ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single",  ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Single",                                                                                                                                                                   ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()",                                                                                                                     ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(MathF.Round(firstOp[0]))",                                                                                                                                                 ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i])"}),
+    ("SimpleUnOpTest.template",      new Dictionary<string, string> { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "RoundToNearestIntegerScalar",   ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double",  ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Double",                                                                                                                                                                   ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()",                                                                                                                     ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Round(firstOp[0], MidpointRounding.AwayFromZero))",                                                                                                                   ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i])"}),
+    ("SimpleUnOpTest.template",      new Dictionary<string, string> { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse",  ["Method"] = "RoundToNearestIntegerScalar",   ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single",  ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Single",                                                                                                                                                                   ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()",                                                                                                                     ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(MathF.Round(firstOp[0], MidpointRounding.AwayFromZero))",                                                                                                                  ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i])"}),
+    ("SimpleUnOpTest.template",      new Dictionary<string, string> { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "RoundToNegativeInfinityScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double",  ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Double",                                                                                                                                                                   ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()",                                                                                                                     ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Floor(firstOp[0]))",                                                                                                                                                  ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i])"}),
+    ("SimpleUnOpTest.template",      new Dictionary<string, string> { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse",  ["Method"] = "RoundToNegativeInfinityScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single",  ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Single",                                                                                                                                                                   ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()",                                                                                                                     ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(MathF.Floor(firstOp[0]))",                                                                                                                                                 ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i])"}),
+    ("SimpleUnOpTest.template",      new Dictionary<string, string> { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse2", ["Method"] = "RoundToPositiveInfinityScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double",  ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Double",                                                                                                                                                                   ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()",                                                                                                                     ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Ceiling(firstOp[0]))",                                                                                                                                                ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i])"}),
+    ("SimpleUnOpTest.template",      new Dictionary<string, string> { ["Isa"] = "Sse41", ["LoadIsa"] = "Sse",  ["Method"] = "RoundToPositiveInfinityScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single",  ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Single",                                                                                                                                                                   ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()",                                                                                                                     ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(MathF.Ceiling(firstOp[0]))",                                                                                                                                               ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i])"}),
+};
+
 private static readonly (string templateFileName, Dictionary<string, string> templateData)[] Sse41X64Inputs = new []
 {
     ("ExtractScalarTest.template",   new Dictionary<string, string> { ["Isa"] = "Sse41.X64", ["LoadIsa"] = "Sse2", ["Method"] = "Extract",                       ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int64",   ["Op1VectorType"] ="Vector128", ["Op1BaseType"] = "Int64",                                                                                                                                                   ["Imm"] = "129", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt64()",                                                                                                                      ["ValidateFirstResult"] = "(result[0] != firstOp[1])"}),
@@ -1349,6 +1361,7 @@ ProcessInputs("Sse2.X64", Sse2X64Inputs);
 ProcessInputs("Sse3", Sse3Inputs);
 ProcessInputs("Ssse3", Ssse3Inputs);
 ProcessInputs("Sse41", Sse41Inputs);
+ProcessInputs("Sse41_Overloaded", Sse41_OverloadedInputs);
 ProcessInputs("Sse41.X64", Sse41X64Inputs);
 ProcessInputs("Sse42", Sse42Inputs);
 ProcessInputs("Avx", AvxInputs);
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/Program.Sse41_Overloaded.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/Program.Sse41_Overloaded.cs
new file mode 100644 (file)
index 0000000..9a3a4a5
--- /dev/null
@@ -0,0 +1,26 @@
+// 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>() {
+                ["RoundCurrentDirectionScalar.Double"] = RoundCurrentDirectionScalarDouble,
+                ["RoundCurrentDirectionScalar.Single"] = RoundCurrentDirectionScalarSingle,
+                ["RoundToNearestIntegerScalar.Double"] = RoundToNearestIntegerScalarDouble,
+                ["RoundToNearestIntegerScalar.Single"] = RoundToNearestIntegerScalarSingle,
+                ["RoundToNegativeInfinityScalar.Double"] = RoundToNegativeInfinityScalarDouble,
+                ["RoundToNegativeInfinityScalar.Single"] = RoundToNegativeInfinityScalarSingle,
+                ["RoundToPositiveInfinityScalar.Double"] = RoundToPositiveInfinityScalarDouble,
+                ["RoundToPositiveInfinityScalar.Single"] = RoundToPositiveInfinityScalarSingle,
+            };
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundCurrentDirectionScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundCurrentDirectionScalar.Double.cs
new file mode 100644 (file)
index 0000000..bde4a73
--- /dev/null
@@ -0,0 +1,541 @@
+// 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\X86\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.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void RoundCurrentDirectionScalarDouble()
+        {
+            var test = new SimpleUnaryOpTest__RoundCurrentDirectionScalarDouble();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.Read
+                test.RunBasicScenario_UnsafeRead();
+
+                if (Sse2.IsSupported)
+                {
+                    // Validates basic functionality works, using Load
+                    test.RunBasicScenario_Load();
+
+                    // Validates basic functionality works, using LoadAligned
+                    test.RunBasicScenario_LoadAligned();
+                }
+
+                // Validates calling via reflection works, using Unsafe.Read
+                test.RunReflectionScenario_UnsafeRead();
+
+                if (Sse2.IsSupported)
+                {
+                    // Validates calling via reflection works, using Load
+                    test.RunReflectionScenario_Load();
+
+                    // Validates calling via reflection works, using LoadAligned
+                    test.RunReflectionScenario_LoadAligned();
+                }
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                if (Sse2.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 (Sse2.IsSupported)
+                {
+                    // Validates passing a local works, using Load
+                    test.RunLclVarScenario_Load();
+
+                    // Validates passing a local works, using LoadAligned
+                    test.RunLclVarScenario_LoadAligned();
+                }
+
+                // Validates passing the field of a local class works
+                test.RunClassLclFldScenario();
+
+                if (Sse2.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 (Sse2.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 (Sse2.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 (Sse2.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__RoundCurrentDirectionScalarDouble
+    {
+        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 != 32 && alignment != 16) || (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__RoundCurrentDirectionScalarDouble testClass)
+            {
+                var result = Sse41.RoundCurrentDirectionScalar(_fld1);
+
+                Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+                testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+            }
+
+            public void RunStructFldScenario_Load(SimpleUnaryOpTest__RoundCurrentDirectionScalarDouble testClass)
+            {
+                fixed (Vector128<Double>* pFld1 = &_fld1)
+                {
+                    var result = Sse41.RoundCurrentDirectionScalar(
+                        Sse2.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__RoundCurrentDirectionScalarDouble()
+        {
+            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__RoundCurrentDirectionScalarDouble()
+        {
+            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 => Sse41.IsSupported;
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+            var result = Sse41.RoundCurrentDirectionScalar(
+                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 = Sse41.RoundCurrentDirectionScalar(
+                Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr))
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunBasicScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+            var result = Sse41.RoundCurrentDirectionScalar(
+                Sse2.LoadAlignedVector128((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(Sse41).GetMethod(nameof(Sse41.RoundCurrentDirectionScalar), 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(Sse41).GetMethod(nameof(Sse41.RoundCurrentDirectionScalar), new Type[] { typeof(Vector128<Double>) })
+                                     .Invoke(null, new object[] {
+                                        Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr))
+                                     });
+
+            Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunReflectionScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+            var result = typeof(Sse41).GetMethod(nameof(Sse41.RoundCurrentDirectionScalar), new Type[] { typeof(Vector128<Double>) })
+                                     .Invoke(null, new object[] {
+                                        Sse2.LoadAlignedVector128((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 = Sse41.RoundCurrentDirectionScalar(
+                _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 = Sse41.RoundCurrentDirectionScalar(
+                    Sse2.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 = Sse41.RoundCurrentDirectionScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_Load()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+            var op1 = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundCurrentDirectionScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+            var op1 = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundCurrentDirectionScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunClassLclFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+            var test = new SimpleUnaryOpTest__RoundCurrentDirectionScalarDouble();
+            var result = Sse41.RoundCurrentDirectionScalar(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__RoundCurrentDirectionScalarDouble();
+
+            fixed (Vector128<Double>* pFld1 = &test._fld1)
+            {
+                var result = Sse41.RoundCurrentDirectionScalar(
+                    Sse2.LoadVector128((Double*)(pFld1))
+                );
+
+                Unsafe.Write(_dataTable.outArrayPtr, result);
+                ValidateResult(test._fld1, _dataTable.outArrayPtr);
+            }
+        }
+
+        public void RunClassFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+            var result = Sse41.RoundCurrentDirectionScalar(_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 = Sse41.RoundCurrentDirectionScalar(
+                    Sse2.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 = Sse41.RoundCurrentDirectionScalar(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 = Sse41.RoundCurrentDirectionScalar(
+                Sse2.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;
+
+            if (BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Round(firstOp[0])))
+            {
+                succeeded = false;
+            }
+            else
+            {
+                for (var i = 1; i < RetElementCount; i++)
+                {
+                    if (BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i]))
+                    {
+                        succeeded = false;
+                        break;
+                    }
+                }
+            }
+
+            if (!succeeded)
+            {
+                TestLibrary.TestFramework.LogInformation($"{nameof(Sse41)}.{nameof(Sse41.RoundCurrentDirectionScalar)}<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;
+            }
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundCurrentDirectionScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundCurrentDirectionScalar.Single.cs
new file mode 100644 (file)
index 0000000..132067f
--- /dev/null
@@ -0,0 +1,541 @@
+// 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\X86\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.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void RoundCurrentDirectionScalarSingle()
+        {
+            var test = new SimpleUnaryOpTest__RoundCurrentDirectionScalarSingle();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.Read
+                test.RunBasicScenario_UnsafeRead();
+
+                if (Sse.IsSupported)
+                {
+                    // Validates basic functionality works, using Load
+                    test.RunBasicScenario_Load();
+
+                    // Validates basic functionality works, using LoadAligned
+                    test.RunBasicScenario_LoadAligned();
+                }
+
+                // Validates calling via reflection works, using Unsafe.Read
+                test.RunReflectionScenario_UnsafeRead();
+
+                if (Sse.IsSupported)
+                {
+                    // Validates calling via reflection works, using Load
+                    test.RunReflectionScenario_Load();
+
+                    // Validates calling via reflection works, using LoadAligned
+                    test.RunReflectionScenario_LoadAligned();
+                }
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                if (Sse.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 (Sse.IsSupported)
+                {
+                    // Validates passing a local works, using Load
+                    test.RunLclVarScenario_Load();
+
+                    // Validates passing a local works, using LoadAligned
+                    test.RunLclVarScenario_LoadAligned();
+                }
+
+                // Validates passing the field of a local class works
+                test.RunClassLclFldScenario();
+
+                if (Sse.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 (Sse.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 (Sse.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 (Sse.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__RoundCurrentDirectionScalarSingle
+    {
+        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 != 32 && alignment != 16) || (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__RoundCurrentDirectionScalarSingle testClass)
+            {
+                var result = Sse41.RoundCurrentDirectionScalar(_fld1);
+
+                Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+                testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+            }
+
+            public void RunStructFldScenario_Load(SimpleUnaryOpTest__RoundCurrentDirectionScalarSingle testClass)
+            {
+                fixed (Vector128<Single>* pFld1 = &_fld1)
+                {
+                    var result = Sse41.RoundCurrentDirectionScalar(
+                        Sse.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__RoundCurrentDirectionScalarSingle()
+        {
+            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__RoundCurrentDirectionScalarSingle()
+        {
+            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 => Sse41.IsSupported;
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+            var result = Sse41.RoundCurrentDirectionScalar(
+                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 = Sse41.RoundCurrentDirectionScalar(
+                Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr))
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunBasicScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+            var result = Sse41.RoundCurrentDirectionScalar(
+                Sse.LoadAlignedVector128((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(Sse41).GetMethod(nameof(Sse41.RoundCurrentDirectionScalar), 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(Sse41).GetMethod(nameof(Sse41.RoundCurrentDirectionScalar), new Type[] { typeof(Vector128<Single>) })
+                                     .Invoke(null, new object[] {
+                                        Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr))
+                                     });
+
+            Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunReflectionScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+            var result = typeof(Sse41).GetMethod(nameof(Sse41.RoundCurrentDirectionScalar), new Type[] { typeof(Vector128<Single>) })
+                                     .Invoke(null, new object[] {
+                                        Sse.LoadAlignedVector128((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 = Sse41.RoundCurrentDirectionScalar(
+                _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 = Sse41.RoundCurrentDirectionScalar(
+                    Sse.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 = Sse41.RoundCurrentDirectionScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_Load()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+            var op1 = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundCurrentDirectionScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+            var op1 = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundCurrentDirectionScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunClassLclFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+            var test = new SimpleUnaryOpTest__RoundCurrentDirectionScalarSingle();
+            var result = Sse41.RoundCurrentDirectionScalar(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__RoundCurrentDirectionScalarSingle();
+
+            fixed (Vector128<Single>* pFld1 = &test._fld1)
+            {
+                var result = Sse41.RoundCurrentDirectionScalar(
+                    Sse.LoadVector128((Single*)(pFld1))
+                );
+
+                Unsafe.Write(_dataTable.outArrayPtr, result);
+                ValidateResult(test._fld1, _dataTable.outArrayPtr);
+            }
+        }
+
+        public void RunClassFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+            var result = Sse41.RoundCurrentDirectionScalar(_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 = Sse41.RoundCurrentDirectionScalar(
+                    Sse.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 = Sse41.RoundCurrentDirectionScalar(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 = Sse41.RoundCurrentDirectionScalar(
+                Sse.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;
+
+            if (BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(MathF.Round(firstOp[0])))
+            {
+                succeeded = false;
+            }
+            else
+            {
+                for (var i = 1; i < RetElementCount; i++)
+                {
+                    if (BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i]))
+                    {
+                        succeeded = false;
+                        break;
+                    }
+                }
+            }
+
+            if (!succeeded)
+            {
+                TestLibrary.TestFramework.LogInformation($"{nameof(Sse41)}.{nameof(Sse41.RoundCurrentDirectionScalar)}<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;
+            }
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToNearestIntegerScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToNearestIntegerScalar.Double.cs
new file mode 100644 (file)
index 0000000..3192fcd
--- /dev/null
@@ -0,0 +1,541 @@
+// 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\X86\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.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void RoundToNearestIntegerScalarDouble()
+        {
+            var test = new SimpleUnaryOpTest__RoundToNearestIntegerScalarDouble();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.Read
+                test.RunBasicScenario_UnsafeRead();
+
+                if (Sse2.IsSupported)
+                {
+                    // Validates basic functionality works, using Load
+                    test.RunBasicScenario_Load();
+
+                    // Validates basic functionality works, using LoadAligned
+                    test.RunBasicScenario_LoadAligned();
+                }
+
+                // Validates calling via reflection works, using Unsafe.Read
+                test.RunReflectionScenario_UnsafeRead();
+
+                if (Sse2.IsSupported)
+                {
+                    // Validates calling via reflection works, using Load
+                    test.RunReflectionScenario_Load();
+
+                    // Validates calling via reflection works, using LoadAligned
+                    test.RunReflectionScenario_LoadAligned();
+                }
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                if (Sse2.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 (Sse2.IsSupported)
+                {
+                    // Validates passing a local works, using Load
+                    test.RunLclVarScenario_Load();
+
+                    // Validates passing a local works, using LoadAligned
+                    test.RunLclVarScenario_LoadAligned();
+                }
+
+                // Validates passing the field of a local class works
+                test.RunClassLclFldScenario();
+
+                if (Sse2.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 (Sse2.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 (Sse2.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 (Sse2.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__RoundToNearestIntegerScalarDouble
+    {
+        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 != 32 && alignment != 16) || (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__RoundToNearestIntegerScalarDouble testClass)
+            {
+                var result = Sse41.RoundToNearestIntegerScalar(_fld1);
+
+                Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+                testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+            }
+
+            public void RunStructFldScenario_Load(SimpleUnaryOpTest__RoundToNearestIntegerScalarDouble testClass)
+            {
+                fixed (Vector128<Double>* pFld1 = &_fld1)
+                {
+                    var result = Sse41.RoundToNearestIntegerScalar(
+                        Sse2.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__RoundToNearestIntegerScalarDouble()
+        {
+            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__RoundToNearestIntegerScalarDouble()
+        {
+            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 => Sse41.IsSupported;
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+            var result = Sse41.RoundToNearestIntegerScalar(
+                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 = Sse41.RoundToNearestIntegerScalar(
+                Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr))
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunBasicScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+            var result = Sse41.RoundToNearestIntegerScalar(
+                Sse2.LoadAlignedVector128((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(Sse41).GetMethod(nameof(Sse41.RoundToNearestIntegerScalar), 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(Sse41).GetMethod(nameof(Sse41.RoundToNearestIntegerScalar), new Type[] { typeof(Vector128<Double>) })
+                                     .Invoke(null, new object[] {
+                                        Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr))
+                                     });
+
+            Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunReflectionScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+            var result = typeof(Sse41).GetMethod(nameof(Sse41.RoundToNearestIntegerScalar), new Type[] { typeof(Vector128<Double>) })
+                                     .Invoke(null, new object[] {
+                                        Sse2.LoadAlignedVector128((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 = Sse41.RoundToNearestIntegerScalar(
+                _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 = Sse41.RoundToNearestIntegerScalar(
+                    Sse2.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 = Sse41.RoundToNearestIntegerScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_Load()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+            var op1 = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundToNearestIntegerScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+            var op1 = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundToNearestIntegerScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunClassLclFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+            var test = new SimpleUnaryOpTest__RoundToNearestIntegerScalarDouble();
+            var result = Sse41.RoundToNearestIntegerScalar(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__RoundToNearestIntegerScalarDouble();
+
+            fixed (Vector128<Double>* pFld1 = &test._fld1)
+            {
+                var result = Sse41.RoundToNearestIntegerScalar(
+                    Sse2.LoadVector128((Double*)(pFld1))
+                );
+
+                Unsafe.Write(_dataTable.outArrayPtr, result);
+                ValidateResult(test._fld1, _dataTable.outArrayPtr);
+            }
+        }
+
+        public void RunClassFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+            var result = Sse41.RoundToNearestIntegerScalar(_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 = Sse41.RoundToNearestIntegerScalar(
+                    Sse2.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 = Sse41.RoundToNearestIntegerScalar(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 = Sse41.RoundToNearestIntegerScalar(
+                Sse2.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;
+
+            if (BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Round(firstOp[0], MidpointRounding.AwayFromZero)))
+            {
+                succeeded = false;
+            }
+            else
+            {
+                for (var i = 1; i < RetElementCount; i++)
+                {
+                    if (BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i]))
+                    {
+                        succeeded = false;
+                        break;
+                    }
+                }
+            }
+
+            if (!succeeded)
+            {
+                TestLibrary.TestFramework.LogInformation($"{nameof(Sse41)}.{nameof(Sse41.RoundToNearestIntegerScalar)}<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;
+            }
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToNearestIntegerScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToNearestIntegerScalar.Single.cs
new file mode 100644 (file)
index 0000000..c79699c
--- /dev/null
@@ -0,0 +1,541 @@
+// 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\X86\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.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void RoundToNearestIntegerScalarSingle()
+        {
+            var test = new SimpleUnaryOpTest__RoundToNearestIntegerScalarSingle();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.Read
+                test.RunBasicScenario_UnsafeRead();
+
+                if (Sse.IsSupported)
+                {
+                    // Validates basic functionality works, using Load
+                    test.RunBasicScenario_Load();
+
+                    // Validates basic functionality works, using LoadAligned
+                    test.RunBasicScenario_LoadAligned();
+                }
+
+                // Validates calling via reflection works, using Unsafe.Read
+                test.RunReflectionScenario_UnsafeRead();
+
+                if (Sse.IsSupported)
+                {
+                    // Validates calling via reflection works, using Load
+                    test.RunReflectionScenario_Load();
+
+                    // Validates calling via reflection works, using LoadAligned
+                    test.RunReflectionScenario_LoadAligned();
+                }
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                if (Sse.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 (Sse.IsSupported)
+                {
+                    // Validates passing a local works, using Load
+                    test.RunLclVarScenario_Load();
+
+                    // Validates passing a local works, using LoadAligned
+                    test.RunLclVarScenario_LoadAligned();
+                }
+
+                // Validates passing the field of a local class works
+                test.RunClassLclFldScenario();
+
+                if (Sse.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 (Sse.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 (Sse.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 (Sse.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__RoundToNearestIntegerScalarSingle
+    {
+        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 != 32 && alignment != 16) || (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__RoundToNearestIntegerScalarSingle testClass)
+            {
+                var result = Sse41.RoundToNearestIntegerScalar(_fld1);
+
+                Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+                testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+            }
+
+            public void RunStructFldScenario_Load(SimpleUnaryOpTest__RoundToNearestIntegerScalarSingle testClass)
+            {
+                fixed (Vector128<Single>* pFld1 = &_fld1)
+                {
+                    var result = Sse41.RoundToNearestIntegerScalar(
+                        Sse.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__RoundToNearestIntegerScalarSingle()
+        {
+            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__RoundToNearestIntegerScalarSingle()
+        {
+            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 => Sse41.IsSupported;
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+            var result = Sse41.RoundToNearestIntegerScalar(
+                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 = Sse41.RoundToNearestIntegerScalar(
+                Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr))
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunBasicScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+            var result = Sse41.RoundToNearestIntegerScalar(
+                Sse.LoadAlignedVector128((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(Sse41).GetMethod(nameof(Sse41.RoundToNearestIntegerScalar), 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(Sse41).GetMethod(nameof(Sse41.RoundToNearestIntegerScalar), new Type[] { typeof(Vector128<Single>) })
+                                     .Invoke(null, new object[] {
+                                        Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr))
+                                     });
+
+            Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunReflectionScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+            var result = typeof(Sse41).GetMethod(nameof(Sse41.RoundToNearestIntegerScalar), new Type[] { typeof(Vector128<Single>) })
+                                     .Invoke(null, new object[] {
+                                        Sse.LoadAlignedVector128((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 = Sse41.RoundToNearestIntegerScalar(
+                _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 = Sse41.RoundToNearestIntegerScalar(
+                    Sse.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 = Sse41.RoundToNearestIntegerScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_Load()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+            var op1 = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundToNearestIntegerScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+            var op1 = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundToNearestIntegerScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunClassLclFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+            var test = new SimpleUnaryOpTest__RoundToNearestIntegerScalarSingle();
+            var result = Sse41.RoundToNearestIntegerScalar(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__RoundToNearestIntegerScalarSingle();
+
+            fixed (Vector128<Single>* pFld1 = &test._fld1)
+            {
+                var result = Sse41.RoundToNearestIntegerScalar(
+                    Sse.LoadVector128((Single*)(pFld1))
+                );
+
+                Unsafe.Write(_dataTable.outArrayPtr, result);
+                ValidateResult(test._fld1, _dataTable.outArrayPtr);
+            }
+        }
+
+        public void RunClassFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+            var result = Sse41.RoundToNearestIntegerScalar(_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 = Sse41.RoundToNearestIntegerScalar(
+                    Sse.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 = Sse41.RoundToNearestIntegerScalar(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 = Sse41.RoundToNearestIntegerScalar(
+                Sse.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;
+
+            if (BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(MathF.Round(firstOp[0], MidpointRounding.AwayFromZero)))
+            {
+                succeeded = false;
+            }
+            else
+            {
+                for (var i = 1; i < RetElementCount; i++)
+                {
+                    if (BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i]))
+                    {
+                        succeeded = false;
+                        break;
+                    }
+                }
+            }
+
+            if (!succeeded)
+            {
+                TestLibrary.TestFramework.LogInformation($"{nameof(Sse41)}.{nameof(Sse41.RoundToNearestIntegerScalar)}<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;
+            }
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToNegativeInfinityScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToNegativeInfinityScalar.Double.cs
new file mode 100644 (file)
index 0000000..42d0c1a
--- /dev/null
@@ -0,0 +1,541 @@
+// 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\X86\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.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void RoundToNegativeInfinityScalarDouble()
+        {
+            var test = new SimpleUnaryOpTest__RoundToNegativeInfinityScalarDouble();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.Read
+                test.RunBasicScenario_UnsafeRead();
+
+                if (Sse2.IsSupported)
+                {
+                    // Validates basic functionality works, using Load
+                    test.RunBasicScenario_Load();
+
+                    // Validates basic functionality works, using LoadAligned
+                    test.RunBasicScenario_LoadAligned();
+                }
+
+                // Validates calling via reflection works, using Unsafe.Read
+                test.RunReflectionScenario_UnsafeRead();
+
+                if (Sse2.IsSupported)
+                {
+                    // Validates calling via reflection works, using Load
+                    test.RunReflectionScenario_Load();
+
+                    // Validates calling via reflection works, using LoadAligned
+                    test.RunReflectionScenario_LoadAligned();
+                }
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                if (Sse2.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 (Sse2.IsSupported)
+                {
+                    // Validates passing a local works, using Load
+                    test.RunLclVarScenario_Load();
+
+                    // Validates passing a local works, using LoadAligned
+                    test.RunLclVarScenario_LoadAligned();
+                }
+
+                // Validates passing the field of a local class works
+                test.RunClassLclFldScenario();
+
+                if (Sse2.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 (Sse2.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 (Sse2.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 (Sse2.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__RoundToNegativeInfinityScalarDouble
+    {
+        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 != 32 && alignment != 16) || (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__RoundToNegativeInfinityScalarDouble testClass)
+            {
+                var result = Sse41.RoundToNegativeInfinityScalar(_fld1);
+
+                Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+                testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+            }
+
+            public void RunStructFldScenario_Load(SimpleUnaryOpTest__RoundToNegativeInfinityScalarDouble testClass)
+            {
+                fixed (Vector128<Double>* pFld1 = &_fld1)
+                {
+                    var result = Sse41.RoundToNegativeInfinityScalar(
+                        Sse2.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__RoundToNegativeInfinityScalarDouble()
+        {
+            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__RoundToNegativeInfinityScalarDouble()
+        {
+            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 => Sse41.IsSupported;
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+            var result = Sse41.RoundToNegativeInfinityScalar(
+                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 = Sse41.RoundToNegativeInfinityScalar(
+                Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr))
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunBasicScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+            var result = Sse41.RoundToNegativeInfinityScalar(
+                Sse2.LoadAlignedVector128((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(Sse41).GetMethod(nameof(Sse41.RoundToNegativeInfinityScalar), 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(Sse41).GetMethod(nameof(Sse41.RoundToNegativeInfinityScalar), new Type[] { typeof(Vector128<Double>) })
+                                     .Invoke(null, new object[] {
+                                        Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr))
+                                     });
+
+            Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunReflectionScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+            var result = typeof(Sse41).GetMethod(nameof(Sse41.RoundToNegativeInfinityScalar), new Type[] { typeof(Vector128<Double>) })
+                                     .Invoke(null, new object[] {
+                                        Sse2.LoadAlignedVector128((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 = Sse41.RoundToNegativeInfinityScalar(
+                _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 = Sse41.RoundToNegativeInfinityScalar(
+                    Sse2.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 = Sse41.RoundToNegativeInfinityScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_Load()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+            var op1 = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundToNegativeInfinityScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+            var op1 = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundToNegativeInfinityScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunClassLclFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+            var test = new SimpleUnaryOpTest__RoundToNegativeInfinityScalarDouble();
+            var result = Sse41.RoundToNegativeInfinityScalar(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__RoundToNegativeInfinityScalarDouble();
+
+            fixed (Vector128<Double>* pFld1 = &test._fld1)
+            {
+                var result = Sse41.RoundToNegativeInfinityScalar(
+                    Sse2.LoadVector128((Double*)(pFld1))
+                );
+
+                Unsafe.Write(_dataTable.outArrayPtr, result);
+                ValidateResult(test._fld1, _dataTable.outArrayPtr);
+            }
+        }
+
+        public void RunClassFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+            var result = Sse41.RoundToNegativeInfinityScalar(_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 = Sse41.RoundToNegativeInfinityScalar(
+                    Sse2.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 = Sse41.RoundToNegativeInfinityScalar(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 = Sse41.RoundToNegativeInfinityScalar(
+                Sse2.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;
+
+            if (BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Floor(firstOp[0])))
+            {
+                succeeded = false;
+            }
+            else
+            {
+                for (var i = 1; i < RetElementCount; i++)
+                {
+                    if (BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i]))
+                    {
+                        succeeded = false;
+                        break;
+                    }
+                }
+            }
+
+            if (!succeeded)
+            {
+                TestLibrary.TestFramework.LogInformation($"{nameof(Sse41)}.{nameof(Sse41.RoundToNegativeInfinityScalar)}<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;
+            }
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToNegativeInfinityScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToNegativeInfinityScalar.Single.cs
new file mode 100644 (file)
index 0000000..b8268d8
--- /dev/null
@@ -0,0 +1,541 @@
+// 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\X86\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.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void RoundToNegativeInfinityScalarSingle()
+        {
+            var test = new SimpleUnaryOpTest__RoundToNegativeInfinityScalarSingle();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.Read
+                test.RunBasicScenario_UnsafeRead();
+
+                if (Sse.IsSupported)
+                {
+                    // Validates basic functionality works, using Load
+                    test.RunBasicScenario_Load();
+
+                    // Validates basic functionality works, using LoadAligned
+                    test.RunBasicScenario_LoadAligned();
+                }
+
+                // Validates calling via reflection works, using Unsafe.Read
+                test.RunReflectionScenario_UnsafeRead();
+
+                if (Sse.IsSupported)
+                {
+                    // Validates calling via reflection works, using Load
+                    test.RunReflectionScenario_Load();
+
+                    // Validates calling via reflection works, using LoadAligned
+                    test.RunReflectionScenario_LoadAligned();
+                }
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                if (Sse.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 (Sse.IsSupported)
+                {
+                    // Validates passing a local works, using Load
+                    test.RunLclVarScenario_Load();
+
+                    // Validates passing a local works, using LoadAligned
+                    test.RunLclVarScenario_LoadAligned();
+                }
+
+                // Validates passing the field of a local class works
+                test.RunClassLclFldScenario();
+
+                if (Sse.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 (Sse.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 (Sse.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 (Sse.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__RoundToNegativeInfinityScalarSingle
+    {
+        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 != 32 && alignment != 16) || (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__RoundToNegativeInfinityScalarSingle testClass)
+            {
+                var result = Sse41.RoundToNegativeInfinityScalar(_fld1);
+
+                Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+                testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+            }
+
+            public void RunStructFldScenario_Load(SimpleUnaryOpTest__RoundToNegativeInfinityScalarSingle testClass)
+            {
+                fixed (Vector128<Single>* pFld1 = &_fld1)
+                {
+                    var result = Sse41.RoundToNegativeInfinityScalar(
+                        Sse.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__RoundToNegativeInfinityScalarSingle()
+        {
+            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__RoundToNegativeInfinityScalarSingle()
+        {
+            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 => Sse41.IsSupported;
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+            var result = Sse41.RoundToNegativeInfinityScalar(
+                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 = Sse41.RoundToNegativeInfinityScalar(
+                Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr))
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunBasicScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+            var result = Sse41.RoundToNegativeInfinityScalar(
+                Sse.LoadAlignedVector128((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(Sse41).GetMethod(nameof(Sse41.RoundToNegativeInfinityScalar), 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(Sse41).GetMethod(nameof(Sse41.RoundToNegativeInfinityScalar), new Type[] { typeof(Vector128<Single>) })
+                                     .Invoke(null, new object[] {
+                                        Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr))
+                                     });
+
+            Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunReflectionScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+            var result = typeof(Sse41).GetMethod(nameof(Sse41.RoundToNegativeInfinityScalar), new Type[] { typeof(Vector128<Single>) })
+                                     .Invoke(null, new object[] {
+                                        Sse.LoadAlignedVector128((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 = Sse41.RoundToNegativeInfinityScalar(
+                _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 = Sse41.RoundToNegativeInfinityScalar(
+                    Sse.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 = Sse41.RoundToNegativeInfinityScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_Load()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+            var op1 = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundToNegativeInfinityScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+            var op1 = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundToNegativeInfinityScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunClassLclFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+            var test = new SimpleUnaryOpTest__RoundToNegativeInfinityScalarSingle();
+            var result = Sse41.RoundToNegativeInfinityScalar(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__RoundToNegativeInfinityScalarSingle();
+
+            fixed (Vector128<Single>* pFld1 = &test._fld1)
+            {
+                var result = Sse41.RoundToNegativeInfinityScalar(
+                    Sse.LoadVector128((Single*)(pFld1))
+                );
+
+                Unsafe.Write(_dataTable.outArrayPtr, result);
+                ValidateResult(test._fld1, _dataTable.outArrayPtr);
+            }
+        }
+
+        public void RunClassFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+            var result = Sse41.RoundToNegativeInfinityScalar(_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 = Sse41.RoundToNegativeInfinityScalar(
+                    Sse.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 = Sse41.RoundToNegativeInfinityScalar(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 = Sse41.RoundToNegativeInfinityScalar(
+                Sse.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;
+
+            if (BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(MathF.Floor(firstOp[0])))
+            {
+                succeeded = false;
+            }
+            else
+            {
+                for (var i = 1; i < RetElementCount; i++)
+                {
+                    if (BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i]))
+                    {
+                        succeeded = false;
+                        break;
+                    }
+                }
+            }
+
+            if (!succeeded)
+            {
+                TestLibrary.TestFramework.LogInformation($"{nameof(Sse41)}.{nameof(Sse41.RoundToNegativeInfinityScalar)}<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;
+            }
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToPositiveInfinityScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToPositiveInfinityScalar.Double.cs
new file mode 100644 (file)
index 0000000..22e23d4
--- /dev/null
@@ -0,0 +1,541 @@
+// 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\X86\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.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void RoundToPositiveInfinityScalarDouble()
+        {
+            var test = new SimpleUnaryOpTest__RoundToPositiveInfinityScalarDouble();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.Read
+                test.RunBasicScenario_UnsafeRead();
+
+                if (Sse2.IsSupported)
+                {
+                    // Validates basic functionality works, using Load
+                    test.RunBasicScenario_Load();
+
+                    // Validates basic functionality works, using LoadAligned
+                    test.RunBasicScenario_LoadAligned();
+                }
+
+                // Validates calling via reflection works, using Unsafe.Read
+                test.RunReflectionScenario_UnsafeRead();
+
+                if (Sse2.IsSupported)
+                {
+                    // Validates calling via reflection works, using Load
+                    test.RunReflectionScenario_Load();
+
+                    // Validates calling via reflection works, using LoadAligned
+                    test.RunReflectionScenario_LoadAligned();
+                }
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                if (Sse2.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 (Sse2.IsSupported)
+                {
+                    // Validates passing a local works, using Load
+                    test.RunLclVarScenario_Load();
+
+                    // Validates passing a local works, using LoadAligned
+                    test.RunLclVarScenario_LoadAligned();
+                }
+
+                // Validates passing the field of a local class works
+                test.RunClassLclFldScenario();
+
+                if (Sse2.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 (Sse2.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 (Sse2.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 (Sse2.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__RoundToPositiveInfinityScalarDouble
+    {
+        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 != 32 && alignment != 16) || (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__RoundToPositiveInfinityScalarDouble testClass)
+            {
+                var result = Sse41.RoundToPositiveInfinityScalar(_fld1);
+
+                Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+                testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+            }
+
+            public void RunStructFldScenario_Load(SimpleUnaryOpTest__RoundToPositiveInfinityScalarDouble testClass)
+            {
+                fixed (Vector128<Double>* pFld1 = &_fld1)
+                {
+                    var result = Sse41.RoundToPositiveInfinityScalar(
+                        Sse2.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__RoundToPositiveInfinityScalarDouble()
+        {
+            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__RoundToPositiveInfinityScalarDouble()
+        {
+            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 => Sse41.IsSupported;
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+            var result = Sse41.RoundToPositiveInfinityScalar(
+                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 = Sse41.RoundToPositiveInfinityScalar(
+                Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr))
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunBasicScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+            var result = Sse41.RoundToPositiveInfinityScalar(
+                Sse2.LoadAlignedVector128((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(Sse41).GetMethod(nameof(Sse41.RoundToPositiveInfinityScalar), 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(Sse41).GetMethod(nameof(Sse41.RoundToPositiveInfinityScalar), new Type[] { typeof(Vector128<Double>) })
+                                     .Invoke(null, new object[] {
+                                        Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr))
+                                     });
+
+            Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunReflectionScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+            var result = typeof(Sse41).GetMethod(nameof(Sse41.RoundToPositiveInfinityScalar), new Type[] { typeof(Vector128<Double>) })
+                                     .Invoke(null, new object[] {
+                                        Sse2.LoadAlignedVector128((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 = Sse41.RoundToPositiveInfinityScalar(
+                _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 = Sse41.RoundToPositiveInfinityScalar(
+                    Sse2.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 = Sse41.RoundToPositiveInfinityScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_Load()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+            var op1 = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundToPositiveInfinityScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+            var op1 = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundToPositiveInfinityScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunClassLclFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+            var test = new SimpleUnaryOpTest__RoundToPositiveInfinityScalarDouble();
+            var result = Sse41.RoundToPositiveInfinityScalar(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__RoundToPositiveInfinityScalarDouble();
+
+            fixed (Vector128<Double>* pFld1 = &test._fld1)
+            {
+                var result = Sse41.RoundToPositiveInfinityScalar(
+                    Sse2.LoadVector128((Double*)(pFld1))
+                );
+
+                Unsafe.Write(_dataTable.outArrayPtr, result);
+                ValidateResult(test._fld1, _dataTable.outArrayPtr);
+            }
+        }
+
+        public void RunClassFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+            var result = Sse41.RoundToPositiveInfinityScalar(_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 = Sse41.RoundToPositiveInfinityScalar(
+                    Sse2.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 = Sse41.RoundToPositiveInfinityScalar(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 = Sse41.RoundToPositiveInfinityScalar(
+                Sse2.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;
+
+            if (BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(Math.Ceiling(firstOp[0])))
+            {
+                succeeded = false;
+            }
+            else
+            {
+                for (var i = 1; i < RetElementCount; i++)
+                {
+                    if (BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(firstOp[i]))
+                    {
+                        succeeded = false;
+                        break;
+                    }
+                }
+            }
+
+            if (!succeeded)
+            {
+                TestLibrary.TestFramework.LogInformation($"{nameof(Sse41)}.{nameof(Sse41.RoundToPositiveInfinityScalar)}<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;
+            }
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToPositiveInfinityScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/RoundToPositiveInfinityScalar.Single.cs
new file mode 100644 (file)
index 0000000..eeae997
--- /dev/null
@@ -0,0 +1,541 @@
+// 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\X86\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.X86;
+
+namespace JIT.HardwareIntrinsics.X86
+{
+    public static partial class Program
+    {
+        private static void RoundToPositiveInfinityScalarSingle()
+        {
+            var test = new SimpleUnaryOpTest__RoundToPositiveInfinityScalarSingle();
+
+            if (test.IsSupported)
+            {
+                // Validates basic functionality works, using Unsafe.Read
+                test.RunBasicScenario_UnsafeRead();
+
+                if (Sse.IsSupported)
+                {
+                    // Validates basic functionality works, using Load
+                    test.RunBasicScenario_Load();
+
+                    // Validates basic functionality works, using LoadAligned
+                    test.RunBasicScenario_LoadAligned();
+                }
+
+                // Validates calling via reflection works, using Unsafe.Read
+                test.RunReflectionScenario_UnsafeRead();
+
+                if (Sse.IsSupported)
+                {
+                    // Validates calling via reflection works, using Load
+                    test.RunReflectionScenario_Load();
+
+                    // Validates calling via reflection works, using LoadAligned
+                    test.RunReflectionScenario_LoadAligned();
+                }
+
+                // Validates passing a static member works
+                test.RunClsVarScenario();
+
+                if (Sse.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 (Sse.IsSupported)
+                {
+                    // Validates passing a local works, using Load
+                    test.RunLclVarScenario_Load();
+
+                    // Validates passing a local works, using LoadAligned
+                    test.RunLclVarScenario_LoadAligned();
+                }
+
+                // Validates passing the field of a local class works
+                test.RunClassLclFldScenario();
+
+                if (Sse.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 (Sse.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 (Sse.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 (Sse.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__RoundToPositiveInfinityScalarSingle
+    {
+        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 != 32 && alignment != 16) || (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__RoundToPositiveInfinityScalarSingle testClass)
+            {
+                var result = Sse41.RoundToPositiveInfinityScalar(_fld1);
+
+                Unsafe.Write(testClass._dataTable.outArrayPtr, result);
+                testClass.ValidateResult(_fld1, testClass._dataTable.outArrayPtr);
+            }
+
+            public void RunStructFldScenario_Load(SimpleUnaryOpTest__RoundToPositiveInfinityScalarSingle testClass)
+            {
+                fixed (Vector128<Single>* pFld1 = &_fld1)
+                {
+                    var result = Sse41.RoundToPositiveInfinityScalar(
+                        Sse.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__RoundToPositiveInfinityScalarSingle()
+        {
+            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__RoundToPositiveInfinityScalarSingle()
+        {
+            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 => Sse41.IsSupported;
+
+        public bool Succeeded { get; set; }
+
+        public void RunBasicScenario_UnsafeRead()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+            var result = Sse41.RoundToPositiveInfinityScalar(
+                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 = Sse41.RoundToPositiveInfinityScalar(
+                Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr))
+            );
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunBasicScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned));
+
+            var result = Sse41.RoundToPositiveInfinityScalar(
+                Sse.LoadAlignedVector128((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(Sse41).GetMethod(nameof(Sse41.RoundToPositiveInfinityScalar), 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(Sse41).GetMethod(nameof(Sse41.RoundToPositiveInfinityScalar), new Type[] { typeof(Vector128<Single>) })
+                                     .Invoke(null, new object[] {
+                                        Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr))
+                                     });
+
+            Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+            ValidateResult(_dataTable.inArray1Ptr, _dataTable.outArrayPtr);
+        }
+
+        public void RunReflectionScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned));
+
+            var result = typeof(Sse41).GetMethod(nameof(Sse41.RoundToPositiveInfinityScalar), new Type[] { typeof(Vector128<Single>) })
+                                     .Invoke(null, new object[] {
+                                        Sse.LoadAlignedVector128((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 = Sse41.RoundToPositiveInfinityScalar(
+                _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 = Sse41.RoundToPositiveInfinityScalar(
+                    Sse.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 = Sse41.RoundToPositiveInfinityScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_Load()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_Load));
+
+            var op1 = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundToPositiveInfinityScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunLclVarScenario_LoadAligned()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_LoadAligned));
+
+            var op1 = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr));
+            var result = Sse41.RoundToPositiveInfinityScalar(op1);
+
+            Unsafe.Write(_dataTable.outArrayPtr, result);
+            ValidateResult(op1, _dataTable.outArrayPtr);
+        }
+
+        public void RunClassLclFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+            var test = new SimpleUnaryOpTest__RoundToPositiveInfinityScalarSingle();
+            var result = Sse41.RoundToPositiveInfinityScalar(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__RoundToPositiveInfinityScalarSingle();
+
+            fixed (Vector128<Single>* pFld1 = &test._fld1)
+            {
+                var result = Sse41.RoundToPositiveInfinityScalar(
+                    Sse.LoadVector128((Single*)(pFld1))
+                );
+
+                Unsafe.Write(_dataTable.outArrayPtr, result);
+                ValidateResult(test._fld1, _dataTable.outArrayPtr);
+            }
+        }
+
+        public void RunClassFldScenario()
+        {
+            TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+            var result = Sse41.RoundToPositiveInfinityScalar(_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 = Sse41.RoundToPositiveInfinityScalar(
+                    Sse.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 = Sse41.RoundToPositiveInfinityScalar(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 = Sse41.RoundToPositiveInfinityScalar(
+                Sse.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;
+
+            if (BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(MathF.Ceiling(firstOp[0])))
+            {
+                succeeded = false;
+            }
+            else
+            {
+                for (var i = 1; i < RetElementCount; i++)
+                {
+                    if (BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i]))
+                    {
+                        succeeded = false;
+                        break;
+                    }
+                }
+            }
+
+            if (!succeeded)
+            {
+                TestLibrary.TestFramework.LogInformation($"{nameof(Sse41)}.{nameof(Sse41.RoundToPositiveInfinityScalar)}<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;
+            }
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/Sse41_Overloaded_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/Sse41_Overloaded_r.csproj
new file mode 100644 (file)
index 0000000..bf69d56
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <PropertyGroup>
+    <DebugType>Embedded</DebugType>
+    <Optimize></Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="RoundCurrentDirectionScalar.Double.cs" />
+    <Compile Include="RoundCurrentDirectionScalar.Single.cs" />
+    <Compile Include="RoundToNearestIntegerScalar.Double.cs" />
+    <Compile Include="RoundToNearestIntegerScalar.Single.cs" />
+    <Compile Include="RoundToNegativeInfinityScalar.Double.cs" />
+    <Compile Include="RoundToNegativeInfinityScalar.Single.cs" />
+    <Compile Include="RoundToPositiveInfinityScalar.Double.cs" />
+    <Compile Include="RoundToPositiveInfinityScalar.Single.cs" />
+    <Compile Include="Program.Sse41_Overloaded.cs" />
+    <Compile Include="..\Shared\Program.cs" />
+    <Compile Include="..\Shared\SimpleUnOpTest_DataTable.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/Sse41_Overloaded_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse41_Overloaded/Sse41_Overloaded_ro.csproj
new file mode 100644 (file)
index 0000000..a4ed645
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <PropertyGroup>
+    <DebugType>Embedded</DebugType>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="RoundCurrentDirectionScalar.Double.cs" />
+    <Compile Include="RoundCurrentDirectionScalar.Single.cs" />
+    <Compile Include="RoundToNearestIntegerScalar.Double.cs" />
+    <Compile Include="RoundToNearestIntegerScalar.Single.cs" />
+    <Compile Include="RoundToNegativeInfinityScalar.Double.cs" />
+    <Compile Include="RoundToNegativeInfinityScalar.Single.cs" />
+    <Compile Include="RoundToPositiveInfinityScalar.Double.cs" />
+    <Compile Include="RoundToPositiveInfinityScalar.Single.cs" />
+    <Compile Include="Program.Sse41_Overloaded.cs" />
+    <Compile Include="..\Shared\Program.cs" />
+    <Compile Include="..\Shared\SimpleUnOpTest_DataTable.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>