summaryrefslogtreecommitdiff
path: root/tests/src/JIT
diff options
context:
space:
mode:
authorFei Peng <fei.peng@intel.com>2018-12-21 07:14:08 -0800
committerCarol Eidt <carol.eidt@microsoft.com>2018-12-21 07:14:08 -0800
commit7ac4a46d1528484e38e4c808d8a0bbe1b715e0d2 (patch)
tree18e5c0980b784d1c70bc32f32802a3216e5f3b2d /tests/src/JIT
parent0702d6aea34edfe2b86f6a04816bfc147d398c77 (diff)
downloadcoreclr-7ac4a46d1528484e38e4c808d8a0bbe1b715e0d2.tar.gz
coreclr-7ac4a46d1528484e38e4c808d8a0bbe1b715e0d2.tar.bz2
coreclr-7ac4a46d1528484e38e4c808d8a0bbe1b715e0d2.zip
Implement the remaining BMI1/2 intrinsic (#21480)
* Add tests for BMI1/2 intrinsic * Implement the remaining BMI1/2 intrinsic * Fix emitDispIns for BMI instruction
Diffstat (limited to 'tests/src/JIT')
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/BitFieldExtract.UInt64.3Op.cs255
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/BitFieldExtract.UInt64.cs242
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Bmi1.X64_r.csproj2
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Bmi1.X64_ro.csproj2
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Program.Bmi1.X64.cs2
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi1/BitFieldExtract.UInt32.3Op.cs255
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi1/BitFieldExtract.UInt32.cs242
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_r.csproj2
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_ro.csproj2
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Program.Bmi1.cs2
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Bmi2.X64_r.csproj3
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Bmi2.X64_ro.csproj3
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/MultiplyNoFlags.UInt64.BinRes.cs265
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/MultiplyNoFlags.UInt64.cs242
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Program.Bmi2.X64.cs3
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/ZeroHighBits.UInt64.cs242
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Bmi2_r.csproj3
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Bmi2_ro.csproj3
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi2/MultiplyNoFlags.UInt32.BinRes.cs265
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi2/MultiplyNoFlags.UInt32.cs242
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Program.Bmi2.cs3
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Bmi2/ZeroHighBits.UInt32.cs242
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx48
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarBinOpTest.template2
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarTernOpBinResTest.template265
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarTernOpTest.template255
26 files changed, 3077 insertions, 15 deletions
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/BitFieldExtract.UInt64.3Op.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/BitFieldExtract.UInt64.3Op.cs
new file mode 100644
index 0000000000..a6bf026bc8
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/BitFieldExtract.UInt64.3Op.cs
@@ -0,0 +1,255 @@
+// 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 BitFieldExtractUInt643Op()
+ {
+ var test = new ScalarTernOpTest__BitFieldExtractUInt64();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.ReadUnaligned
+ test.RunBasicScenario_UnsafeRead();
+
+ // Validates calling via reflection works, using Unsafe.ReadUnaligned
+ test.RunReflectionScenario_UnsafeRead();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.ReadUnaligned
+ test.RunLclVarScenario_UnsafeRead();
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+ }
+ 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 ScalarTernOpTest__BitFieldExtractUInt64
+ {
+ private struct TestStruct
+ {
+ public UInt64 _fld1;
+ public Byte _fld2;
+ public Byte _fld3;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ testStruct._fld1 = 0x1E00000000000000;
+ testStruct._fld2 = 57;
+ testStruct._fld3 = 4;
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(ScalarTernOpTest__BitFieldExtractUInt64 testClass)
+ {
+ var result = Bmi1.X64.BitFieldExtract(_fld1, _fld2, _fld3);
+ testClass.ValidateResult(_fld1, _fld2, _fld3, result);
+ }
+ }
+
+ private static UInt64 _data1;
+ private static Byte _data2;
+ private static Byte _data3;
+
+ private static UInt64 _clsVar1;
+ private static Byte _clsVar2;
+ private static Byte _clsVar3;
+
+ private UInt64 _fld1;
+ private Byte _fld2;
+ private Byte _fld3;
+
+ static ScalarTernOpTest__BitFieldExtractUInt64()
+ {
+ _clsVar1 = 0x1E00000000000000;
+ _clsVar2 = 57;
+ _clsVar3 = 4;
+ }
+
+ public ScalarTernOpTest__BitFieldExtractUInt64()
+ {
+ Succeeded = true;
+
+ _fld1 = 0x1E00000000000000;
+ _fld2 = 57;
+ _fld3 = 4;
+
+ _data1 = 0x1E00000000000000;
+ _data2 = 57;
+ _data3 = 4;
+ }
+
+ public bool IsSupported => Bmi1.X64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Bmi1.X64.BitFieldExtract(
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<Byte>(ref Unsafe.As<Byte, byte>(ref _data2)),
+ Unsafe.ReadUnaligned<Byte>(ref Unsafe.As<Byte, byte>(ref _data3))
+ );
+
+ ValidateResult(_data1, _data2, _data3, result);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Bmi1.X64).GetMethod(nameof(Bmi1.X64.BitFieldExtract), new Type[] { typeof(UInt64), typeof(Byte), typeof(Byte) })
+ .Invoke(null, new object[] {
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<Byte>(ref Unsafe.As<Byte, byte>(ref _data2)),
+ Unsafe.ReadUnaligned<Byte>(ref Unsafe.As<Byte, byte>(ref _data3))
+ });
+
+ ValidateResult(_data1, _data2, _data3, (UInt64)result);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Bmi1.X64.BitFieldExtract(
+ _clsVar1,
+ _clsVar2,
+ _clsVar3
+ );
+
+ ValidateResult(_clsVar1, _clsVar2, _clsVar3, result);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var data1 = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1));
+ var data2 = Unsafe.ReadUnaligned<Byte>(ref Unsafe.As<Byte, byte>(ref _data2));
+ var data3 = Unsafe.ReadUnaligned<Byte>(ref Unsafe.As<Byte, byte>(ref _data3));
+ var result = Bmi1.X64.BitFieldExtract(data1, data2, data3);
+
+ ValidateResult(data1, data2, data3, result);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new ScalarTernOpTest__BitFieldExtractUInt64();
+ var result = Bmi1.X64.BitFieldExtract(test._fld1, test._fld2, test._fld3);
+
+ ValidateResult(test._fld1, test._fld2, test._fld3, result);
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Bmi1.X64.BitFieldExtract(_fld1, _fld2, _fld3);
+ ValidateResult(_fld1, _fld2, _fld3, result);
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Bmi1.X64.BitFieldExtract(test._fld1, test._fld2, test._fld3);
+
+ ValidateResult(test._fld1, test._fld2, test._fld3, result);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(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(UInt64 op1, Byte op2, Byte op3, UInt64 result, [CallerMemberName] string method = "")
+ {
+ var isUnexpectedResult = false;
+
+ ulong expectedResult = 15; isUnexpectedResult = (expectedResult != result);
+
+ if (isUnexpectedResult)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Bmi1.X64)}.{nameof(Bmi1.X64.BitFieldExtract)}<UInt64>(UInt64, Byte, Byte): BitFieldExtract failed:");
+ TestLibrary.TestFramework.LogInformation($" op1: {op1}");
+ TestLibrary.TestFramework.LogInformation($" op2: {op2}");
+ TestLibrary.TestFramework.LogInformation($" op3: {op3}");
+ TestLibrary.TestFramework.LogInformation($" result: {result}");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/BitFieldExtract.UInt64.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/BitFieldExtract.UInt64.cs
new file mode 100644
index 0000000000..1e97d01a26
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/BitFieldExtract.UInt64.cs
@@ -0,0 +1,242 @@
+// 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 BitFieldExtractUInt64()
+ {
+ var test = new ScalarBinaryOpTest__BitFieldExtractUInt64();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.ReadUnaligned
+ test.RunBasicScenario_UnsafeRead();
+
+ // Validates calling via reflection works, using Unsafe.ReadUnaligned
+ test.RunReflectionScenario_UnsafeRead();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.ReadUnaligned
+ test.RunLclVarScenario_UnsafeRead();
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+ }
+ 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 ScalarBinaryOpTest__BitFieldExtractUInt64
+ {
+ private struct TestStruct
+ {
+ public UInt64 _fld1;
+ public UInt16 _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ testStruct._fld1 = 0x1E00000000000000;
+ testStruct._fld2 = 0x0439;
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(ScalarBinaryOpTest__BitFieldExtractUInt64 testClass)
+ {
+ var result = Bmi1.X64.BitFieldExtract(_fld1, _fld2);
+ testClass.ValidateResult(_fld1, _fld2, result);
+ }
+ }
+
+ private static UInt64 _data1;
+ private static UInt16 _data2;
+
+ private static UInt64 _clsVar1;
+ private static UInt16 _clsVar2;
+
+ private UInt64 _fld1;
+ private UInt16 _fld2;
+
+ static ScalarBinaryOpTest__BitFieldExtractUInt64()
+ {
+ _clsVar1 = 0x1E00000000000000;
+ _clsVar2 = 0x0439;
+ }
+
+ public ScalarBinaryOpTest__BitFieldExtractUInt64()
+ {
+ Succeeded = true;
+
+ _fld1 = 0x1E00000000000000;
+ _fld2 = 0x0439;
+
+ _data1 = 0x1E00000000000000;
+ _data2 = 0x0439;
+ }
+
+ public bool IsSupported => Bmi1.X64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Bmi1.X64.BitFieldExtract(
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt16>(ref Unsafe.As<UInt16, byte>(ref _data2))
+ );
+
+ ValidateResult(_data1, _data2, result);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Bmi1.X64).GetMethod(nameof(Bmi1.X64.BitFieldExtract), new Type[] { typeof(UInt64), typeof(UInt16) })
+ .Invoke(null, new object[] {
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt16>(ref Unsafe.As<UInt16, byte>(ref _data2))
+ });
+
+ ValidateResult(_data1, _data2, (UInt64)result);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Bmi1.X64.BitFieldExtract(
+ _clsVar1,
+ _clsVar2
+ );
+
+ ValidateResult(_clsVar1, _clsVar2, result);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var data1 = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1));
+ var data2 = Unsafe.ReadUnaligned<UInt16>(ref Unsafe.As<UInt16, byte>(ref _data2));
+ var result = Bmi1.X64.BitFieldExtract(data1, data2);
+
+ ValidateResult(data1, data2, result);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new ScalarBinaryOpTest__BitFieldExtractUInt64();
+ var result = Bmi1.X64.BitFieldExtract(test._fld1, test._fld2);
+
+ ValidateResult(test._fld1, test._fld2, result);
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Bmi1.X64.BitFieldExtract(_fld1, _fld2);
+ ValidateResult(_fld1, _fld2, result);
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Bmi1.X64.BitFieldExtract(test._fld1, test._fld2);
+
+ ValidateResult(test._fld1, test._fld2, result);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(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(UInt64 left, UInt16 right, UInt64 result, [CallerMemberName] string method = "")
+ {
+ var isUnexpectedResult = false;
+
+ ulong expectedResult = 15; isUnexpectedResult = (expectedResult != result);
+
+ if (isUnexpectedResult)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Bmi1.X64)}.{nameof(Bmi1.X64.BitFieldExtract)}<UInt64>(UInt64, UInt16): BitFieldExtract failed:");
+ TestLibrary.TestFramework.LogInformation($" left: {left}");
+ TestLibrary.TestFramework.LogInformation($" right: {right}");
+ TestLibrary.TestFramework.LogInformation($" result: {result}");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Bmi1.X64_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Bmi1.X64_r.csproj
index 9e70b4ed56..1d51fa0478 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Bmi1.X64_r.csproj
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Bmi1.X64_r.csproj
@@ -32,6 +32,8 @@
<Compile Include="GetMaskUpToLowestSetBit.UInt64.cs" />
<Compile Include="ResetLowestSetBit.UInt64.cs" />
<Compile Include="TrailingZeroCount.UInt64.cs" />
+ <Compile Include="BitFieldExtract.UInt64.3Op.cs" />
+ <Compile Include="BitFieldExtract.UInt64.cs" />
<Compile Include="Program.Bmi1.X64.cs" />
<Compile Include="..\Shared\Program.cs" />
</ItemGroup>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Bmi1.X64_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Bmi1.X64_ro.csproj
index 464299846a..6617feda98 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Bmi1.X64_ro.csproj
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Bmi1.X64_ro.csproj
@@ -32,6 +32,8 @@
<Compile Include="GetMaskUpToLowestSetBit.UInt64.cs" />
<Compile Include="ResetLowestSetBit.UInt64.cs" />
<Compile Include="TrailingZeroCount.UInt64.cs" />
+ <Compile Include="BitFieldExtract.UInt64.3Op.cs" />
+ <Compile Include="BitFieldExtract.UInt64.cs" />
<Compile Include="Program.Bmi1.X64.cs" />
<Compile Include="..\Shared\Program.cs" />
</ItemGroup>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Program.Bmi1.X64.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Program.Bmi1.X64.cs
index ce22b997ec..a37b7897b8 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Program.Bmi1.X64.cs
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1.X64/Program.Bmi1.X64.cs
@@ -17,6 +17,8 @@ namespace JIT.HardwareIntrinsics.X86
["GetMaskUpToLowestSetBit.UInt64"] = GetMaskUpToLowestSetBitUInt64,
["ResetLowestSetBit.UInt64"] = ResetLowestSetBitUInt64,
["TrailingZeroCount.UInt64"] = TrailingZeroCountUInt64,
+ ["BitFieldExtract.UInt64.3Op"] = BitFieldExtractUInt643Op,
+ ["BitFieldExtract.UInt64"] = BitFieldExtractUInt64,
};
}
}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/BitFieldExtract.UInt32.3Op.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/BitFieldExtract.UInt32.3Op.cs
new file mode 100644
index 0000000000..c93b643747
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/BitFieldExtract.UInt32.3Op.cs
@@ -0,0 +1,255 @@
+// 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 BitFieldExtractUInt323Op()
+ {
+ var test = new ScalarTernOpTest__BitFieldExtractUInt32();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.ReadUnaligned
+ test.RunBasicScenario_UnsafeRead();
+
+ // Validates calling via reflection works, using Unsafe.ReadUnaligned
+ test.RunReflectionScenario_UnsafeRead();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.ReadUnaligned
+ test.RunLclVarScenario_UnsafeRead();
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+ }
+ 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 ScalarTernOpTest__BitFieldExtractUInt32
+ {
+ private struct TestStruct
+ {
+ public UInt32 _fld1;
+ public Byte _fld2;
+ public Byte _fld3;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ testStruct._fld1 = 0x1E000000;
+ testStruct._fld2 = 25;
+ testStruct._fld3 = 4;
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(ScalarTernOpTest__BitFieldExtractUInt32 testClass)
+ {
+ var result = Bmi1.BitFieldExtract(_fld1, _fld2, _fld3);
+ testClass.ValidateResult(_fld1, _fld2, _fld3, result);
+ }
+ }
+
+ private static UInt32 _data1;
+ private static Byte _data2;
+ private static Byte _data3;
+
+ private static UInt32 _clsVar1;
+ private static Byte _clsVar2;
+ private static Byte _clsVar3;
+
+ private UInt32 _fld1;
+ private Byte _fld2;
+ private Byte _fld3;
+
+ static ScalarTernOpTest__BitFieldExtractUInt32()
+ {
+ _clsVar1 = 0x1E000000;
+ _clsVar2 = 25;
+ _clsVar3 = 4;
+ }
+
+ public ScalarTernOpTest__BitFieldExtractUInt32()
+ {
+ Succeeded = true;
+
+ _fld1 = 0x1E000000;
+ _fld2 = 25;
+ _fld3 = 4;
+
+ _data1 = 0x1E000000;
+ _data2 = 25;
+ _data3 = 4;
+ }
+
+ public bool IsSupported => Bmi1.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Bmi1.BitFieldExtract(
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<Byte>(ref Unsafe.As<Byte, byte>(ref _data2)),
+ Unsafe.ReadUnaligned<Byte>(ref Unsafe.As<Byte, byte>(ref _data3))
+ );
+
+ ValidateResult(_data1, _data2, _data3, result);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Bmi1).GetMethod(nameof(Bmi1.BitFieldExtract), new Type[] { typeof(UInt32), typeof(Byte), typeof(Byte) })
+ .Invoke(null, new object[] {
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<Byte>(ref Unsafe.As<Byte, byte>(ref _data2)),
+ Unsafe.ReadUnaligned<Byte>(ref Unsafe.As<Byte, byte>(ref _data3))
+ });
+
+ ValidateResult(_data1, _data2, _data3, (UInt32)result);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Bmi1.BitFieldExtract(
+ _clsVar1,
+ _clsVar2,
+ _clsVar3
+ );
+
+ ValidateResult(_clsVar1, _clsVar2, _clsVar3, result);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var data1 = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1));
+ var data2 = Unsafe.ReadUnaligned<Byte>(ref Unsafe.As<Byte, byte>(ref _data2));
+ var data3 = Unsafe.ReadUnaligned<Byte>(ref Unsafe.As<Byte, byte>(ref _data3));
+ var result = Bmi1.BitFieldExtract(data1, data2, data3);
+
+ ValidateResult(data1, data2, data3, result);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new ScalarTernOpTest__BitFieldExtractUInt32();
+ var result = Bmi1.BitFieldExtract(test._fld1, test._fld2, test._fld3);
+
+ ValidateResult(test._fld1, test._fld2, test._fld3, result);
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Bmi1.BitFieldExtract(_fld1, _fld2, _fld3);
+ ValidateResult(_fld1, _fld2, _fld3, result);
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Bmi1.BitFieldExtract(test._fld1, test._fld2, test._fld3);
+
+ ValidateResult(test._fld1, test._fld2, test._fld3, result);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(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(UInt32 op1, Byte op2, Byte op3, UInt32 result, [CallerMemberName] string method = "")
+ {
+ var isUnexpectedResult = false;
+
+ uint expectedResult = 15; isUnexpectedResult = (expectedResult != result);
+
+ if (isUnexpectedResult)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Bmi1)}.{nameof(Bmi1.BitFieldExtract)}<UInt32>(UInt32, Byte, Byte): BitFieldExtract failed:");
+ TestLibrary.TestFramework.LogInformation($" op1: {op1}");
+ TestLibrary.TestFramework.LogInformation($" op2: {op2}");
+ TestLibrary.TestFramework.LogInformation($" op3: {op3}");
+ TestLibrary.TestFramework.LogInformation($" result: {result}");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/BitFieldExtract.UInt32.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/BitFieldExtract.UInt32.cs
new file mode 100644
index 0000000000..e08e3006b3
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/BitFieldExtract.UInt32.cs
@@ -0,0 +1,242 @@
+// 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 BitFieldExtractUInt32()
+ {
+ var test = new ScalarBinaryOpTest__BitFieldExtractUInt32();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.ReadUnaligned
+ test.RunBasicScenario_UnsafeRead();
+
+ // Validates calling via reflection works, using Unsafe.ReadUnaligned
+ test.RunReflectionScenario_UnsafeRead();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.ReadUnaligned
+ test.RunLclVarScenario_UnsafeRead();
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+ }
+ 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 ScalarBinaryOpTest__BitFieldExtractUInt32
+ {
+ private struct TestStruct
+ {
+ public UInt32 _fld1;
+ public UInt16 _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ testStruct._fld1 = 0x1E000000;
+ testStruct._fld2 = 0x0419;
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(ScalarBinaryOpTest__BitFieldExtractUInt32 testClass)
+ {
+ var result = Bmi1.BitFieldExtract(_fld1, _fld2);
+ testClass.ValidateResult(_fld1, _fld2, result);
+ }
+ }
+
+ private static UInt32 _data1;
+ private static UInt16 _data2;
+
+ private static UInt32 _clsVar1;
+ private static UInt16 _clsVar2;
+
+ private UInt32 _fld1;
+ private UInt16 _fld2;
+
+ static ScalarBinaryOpTest__BitFieldExtractUInt32()
+ {
+ _clsVar1 = 0x1E000000;
+ _clsVar2 = 0x0419;
+ }
+
+ public ScalarBinaryOpTest__BitFieldExtractUInt32()
+ {
+ Succeeded = true;
+
+ _fld1 = 0x1E000000;
+ _fld2 = 0x0419;
+
+ _data1 = 0x1E000000;
+ _data2 = 0x0419;
+ }
+
+ public bool IsSupported => Bmi1.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Bmi1.BitFieldExtract(
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt16>(ref Unsafe.As<UInt16, byte>(ref _data2))
+ );
+
+ ValidateResult(_data1, _data2, result);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Bmi1).GetMethod(nameof(Bmi1.BitFieldExtract), new Type[] { typeof(UInt32), typeof(UInt16) })
+ .Invoke(null, new object[] {
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt16>(ref Unsafe.As<UInt16, byte>(ref _data2))
+ });
+
+ ValidateResult(_data1, _data2, (UInt32)result);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Bmi1.BitFieldExtract(
+ _clsVar1,
+ _clsVar2
+ );
+
+ ValidateResult(_clsVar1, _clsVar2, result);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var data1 = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1));
+ var data2 = Unsafe.ReadUnaligned<UInt16>(ref Unsafe.As<UInt16, byte>(ref _data2));
+ var result = Bmi1.BitFieldExtract(data1, data2);
+
+ ValidateResult(data1, data2, result);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new ScalarBinaryOpTest__BitFieldExtractUInt32();
+ var result = Bmi1.BitFieldExtract(test._fld1, test._fld2);
+
+ ValidateResult(test._fld1, test._fld2, result);
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Bmi1.BitFieldExtract(_fld1, _fld2);
+ ValidateResult(_fld1, _fld2, result);
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Bmi1.BitFieldExtract(test._fld1, test._fld2);
+
+ ValidateResult(test._fld1, test._fld2, result);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(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(UInt32 left, UInt16 right, UInt32 result, [CallerMemberName] string method = "")
+ {
+ var isUnexpectedResult = false;
+
+ uint expectedResult = 15; isUnexpectedResult = (expectedResult != result);
+
+ if (isUnexpectedResult)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Bmi1)}.{nameof(Bmi1.BitFieldExtract)}<UInt32>(UInt32, UInt16): BitFieldExtract failed:");
+ TestLibrary.TestFramework.LogInformation($" left: {left}");
+ TestLibrary.TestFramework.LogInformation($" right: {right}");
+ TestLibrary.TestFramework.LogInformation($" result: {result}");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_r.csproj
index 4b9346525e..96c2b720fc 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_r.csproj
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_r.csproj
@@ -32,6 +32,8 @@
<Compile Include="GetMaskUpToLowestSetBit.UInt32.cs" />
<Compile Include="ResetLowestSetBit.UInt32.cs" />
<Compile Include="TrailingZeroCount.UInt32.cs" />
+ <Compile Include="BitFieldExtract.UInt32.3Op.cs" />
+ <Compile Include="BitFieldExtract.UInt32.cs" />
<Compile Include="Program.Bmi1.cs" />
<Compile Include="..\Shared\Program.cs" />
</ItemGroup>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_ro.csproj
index 7286ee01b8..856710da6a 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_ro.csproj
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Bmi1_ro.csproj
@@ -32,6 +32,8 @@
<Compile Include="GetMaskUpToLowestSetBit.UInt32.cs" />
<Compile Include="ResetLowestSetBit.UInt32.cs" />
<Compile Include="TrailingZeroCount.UInt32.cs" />
+ <Compile Include="BitFieldExtract.UInt32.3Op.cs" />
+ <Compile Include="BitFieldExtract.UInt32.cs" />
<Compile Include="Program.Bmi1.cs" />
<Compile Include="..\Shared\Program.cs" />
</ItemGroup>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Program.Bmi1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Program.Bmi1.cs
index a93c4a5d50..1053bc203a 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Program.Bmi1.cs
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi1/Program.Bmi1.cs
@@ -17,6 +17,8 @@ namespace JIT.HardwareIntrinsics.X86
["GetMaskUpToLowestSetBit.UInt32"] = GetMaskUpToLowestSetBitUInt32,
["ResetLowestSetBit.UInt32"] = ResetLowestSetBitUInt32,
["TrailingZeroCount.UInt32"] = TrailingZeroCountUInt32,
+ ["BitFieldExtract.UInt32.3Op"] = BitFieldExtractUInt323Op,
+ ["BitFieldExtract.UInt32"] = BitFieldExtractUInt32,
};
}
}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Bmi2.X64_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Bmi2.X64_r.csproj
index e620aa1291..45c6e6c520 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Bmi2.X64_r.csproj
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Bmi2.X64_r.csproj
@@ -29,6 +29,9 @@
<ItemGroup>
<Compile Include="ParallelBitDeposit.UInt64.cs" />
<Compile Include="ParallelBitExtract.UInt64.cs" />
+ <Compile Include="ZeroHighBits.UInt64.cs" />
+ <Compile Include="MultiplyNoFlags.UInt64.cs" />
+ <Compile Include="MultiplyNoFlags.UInt64.BinRes.cs" />
<Compile Include="Program.Bmi2.X64.cs" />
<Compile Include="..\Shared\Program.cs" />
</ItemGroup>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Bmi2.X64_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Bmi2.X64_ro.csproj
index 0c28c955c9..a0506e9452 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Bmi2.X64_ro.csproj
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Bmi2.X64_ro.csproj
@@ -29,6 +29,9 @@
<ItemGroup>
<Compile Include="ParallelBitDeposit.UInt64.cs" />
<Compile Include="ParallelBitExtract.UInt64.cs" />
+ <Compile Include="ZeroHighBits.UInt64.cs" />
+ <Compile Include="MultiplyNoFlags.UInt64.cs" />
+ <Compile Include="MultiplyNoFlags.UInt64.BinRes.cs" />
<Compile Include="Program.Bmi2.X64.cs" />
<Compile Include="..\Shared\Program.cs" />
</ItemGroup>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/MultiplyNoFlags.UInt64.BinRes.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/MultiplyNoFlags.UInt64.BinRes.cs
new file mode 100644
index 0000000000..83529943e0
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/MultiplyNoFlags.UInt64.BinRes.cs
@@ -0,0 +1,265 @@
+// 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.Reflection;
+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 MultiplyNoFlagsUInt64BinRes()
+ {
+ var test = new ScalarTernOpBinResTest__MultiplyNoFlagsUInt64();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.ReadUnaligned
+ test.RunBasicScenario_UnsafeRead();
+
+ // Validates calling via reflection works, using Unsafe.ReadUnaligned
+ test.RunReflectionScenario_UnsafeRead();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.ReadUnaligned
+ test.RunLclVarScenario_UnsafeRead();
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+ }
+ 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 ScalarTernOpBinResTest__MultiplyNoFlagsUInt64
+ {
+ private struct TestStruct
+ {
+ public UInt64 _fld1;
+ public UInt64 _fld2;
+ public UInt64 _fld3;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ testStruct._fld1 = UInt64.MaxValue;
+ testStruct._fld2 = UInt64.MaxValue;
+ testStruct._fld3 = 0;
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(ScalarTernOpBinResTest__MultiplyNoFlagsUInt64 testClass)
+ {
+ UInt64 buffer = 0;
+ var result = Bmi2.X64.MultiplyNoFlags(_fld1, _fld2, &buffer);
+ testClass.ValidateResult(_fld1, _fld2, buffer, result);
+ }
+ }
+
+ private static UInt64 _data1;
+ private static UInt64 _data2;
+ private static UInt64 _data3;
+
+ private static UInt64 _clsVar1;
+ private static UInt64 _clsVar2;
+ private static UInt64 _clsVar3;
+
+ private UInt64 _fld1;
+ private UInt64 _fld2;
+ private UInt64 _fld3;
+
+ static ScalarTernOpBinResTest__MultiplyNoFlagsUInt64()
+ {
+ _clsVar1 = UInt64.MaxValue;
+ _clsVar2 = UInt64.MaxValue;
+ _clsVar3 = 0;
+ }
+
+ public ScalarTernOpBinResTest__MultiplyNoFlagsUInt64()
+ {
+ Succeeded = true;
+
+ _fld1 = UInt64.MaxValue;
+ _fld2 = UInt64.MaxValue;
+ _fld3 = 0;
+
+ _data1 = UInt64.MaxValue;
+ _data2 = UInt64.MaxValue;
+ _data3 = 0;
+ }
+
+ public bool IsSupported => Bmi2.X64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ UInt64 buffer = 0;
+
+ var result = Bmi2.X64.MultiplyNoFlags(
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data2)),
+ &buffer
+ );
+
+ ValidateResult(_data1, _data2, buffer, result);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ UInt64 buffer = 0;
+
+ var result = typeof(Bmi2.X64).GetMethod(nameof(Bmi2.X64.MultiplyNoFlags), new Type[] { typeof(UInt64), typeof(UInt64), typeof(UInt64*) })
+ .Invoke(null, new object[] {
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data2)),
+ Pointer.Box(&buffer, typeof(UInt64*))
+ });
+
+ ValidateResult(_data1, _data2, buffer, (UInt64)result);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+ UInt64 buffer = 0;
+ var result = Bmi2.X64.MultiplyNoFlags(
+ _clsVar1,
+ _clsVar2,
+ &buffer
+ );
+
+ ValidateResult(_clsVar1, _clsVar2, buffer, result);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var data1 = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1));
+ var data2 = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data2));
+ var data3 = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data3));
+ var result = Bmi2.X64.MultiplyNoFlags(data1, data2, &data3);
+
+ ValidateResult(data1, data2, data3, result);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ UInt64 buffer = 0;
+
+ var test = new ScalarTernOpBinResTest__MultiplyNoFlagsUInt64();
+ var result = Bmi2.X64.MultiplyNoFlags(test._fld1, test._fld2, &buffer);
+
+ ValidateResult(test._fld1, test._fld2, buffer, result);
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ UInt64 buffer = 0;
+
+ var result = Bmi2.X64.MultiplyNoFlags(_fld1, _fld2, &buffer);
+ ValidateResult(_fld1, _fld2, buffer, result);
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Bmi2.X64.MultiplyNoFlags(test._fld1, test._fld2, &test._fld3);
+
+ ValidateResult(test._fld1, test._fld2, test._fld3, result);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(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(UInt64 op1, UInt64 op2, UInt64 lower, UInt64 higher, [CallerMemberName] string method = "")
+ {
+ var isUnexpectedResult = false;
+
+ ulong expectedHigher = 18446744073709551614, expectedLower = 1; isUnexpectedResult = (expectedHigher != higher) || (expectedLower != lower);
+
+ if (isUnexpectedResult)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Bmi2.X64)}.{nameof(Bmi2.X64.MultiplyNoFlags)}<UInt64>(UInt64, UInt64, UInt64): MultiplyNoFlags failed:");
+ TestLibrary.TestFramework.LogInformation($" op1: {op1}");
+ TestLibrary.TestFramework.LogInformation($" op2: {op2}");
+ TestLibrary.TestFramework.LogInformation($" lower: {lower}");
+ TestLibrary.TestFramework.LogInformation($"higher: {higher}");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/MultiplyNoFlags.UInt64.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/MultiplyNoFlags.UInt64.cs
new file mode 100644
index 0000000000..78d5a7e80b
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/MultiplyNoFlags.UInt64.cs
@@ -0,0 +1,242 @@
+// 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 MultiplyNoFlagsUInt64()
+ {
+ var test = new ScalarBinaryOpTest__MultiplyNoFlagsUInt64();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.ReadUnaligned
+ test.RunBasicScenario_UnsafeRead();
+
+ // Validates calling via reflection works, using Unsafe.ReadUnaligned
+ test.RunReflectionScenario_UnsafeRead();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.ReadUnaligned
+ test.RunLclVarScenario_UnsafeRead();
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+ }
+ 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 ScalarBinaryOpTest__MultiplyNoFlagsUInt64
+ {
+ private struct TestStruct
+ {
+ public UInt64 _fld1;
+ public UInt64 _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ testStruct._fld1 = UInt64.MaxValue;
+ testStruct._fld2 = UInt64.MaxValue;
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(ScalarBinaryOpTest__MultiplyNoFlagsUInt64 testClass)
+ {
+ var result = Bmi2.X64.MultiplyNoFlags(_fld1, _fld2);
+ testClass.ValidateResult(_fld1, _fld2, result);
+ }
+ }
+
+ private static UInt64 _data1;
+ private static UInt64 _data2;
+
+ private static UInt64 _clsVar1;
+ private static UInt64 _clsVar2;
+
+ private UInt64 _fld1;
+ private UInt64 _fld2;
+
+ static ScalarBinaryOpTest__MultiplyNoFlagsUInt64()
+ {
+ _clsVar1 = UInt64.MaxValue;
+ _clsVar2 = UInt64.MaxValue;
+ }
+
+ public ScalarBinaryOpTest__MultiplyNoFlagsUInt64()
+ {
+ Succeeded = true;
+
+ _fld1 = UInt64.MaxValue;
+ _fld2 = UInt64.MaxValue;
+
+ _data1 = UInt64.MaxValue;
+ _data2 = UInt64.MaxValue;
+ }
+
+ public bool IsSupported => Bmi2.X64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Bmi2.X64.MultiplyNoFlags(
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data2))
+ );
+
+ ValidateResult(_data1, _data2, result);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Bmi2.X64).GetMethod(nameof(Bmi2.X64.MultiplyNoFlags), new Type[] { typeof(UInt64), typeof(UInt64) })
+ .Invoke(null, new object[] {
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data2))
+ });
+
+ ValidateResult(_data1, _data2, (UInt64)result);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Bmi2.X64.MultiplyNoFlags(
+ _clsVar1,
+ _clsVar2
+ );
+
+ ValidateResult(_clsVar1, _clsVar2, result);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var data1 = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1));
+ var data2 = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data2));
+ var result = Bmi2.X64.MultiplyNoFlags(data1, data2);
+
+ ValidateResult(data1, data2, result);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new ScalarBinaryOpTest__MultiplyNoFlagsUInt64();
+ var result = Bmi2.X64.MultiplyNoFlags(test._fld1, test._fld2);
+
+ ValidateResult(test._fld1, test._fld2, result);
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Bmi2.X64.MultiplyNoFlags(_fld1, _fld2);
+ ValidateResult(_fld1, _fld2, result);
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Bmi2.X64.MultiplyNoFlags(test._fld1, test._fld2);
+
+ ValidateResult(test._fld1, test._fld2, result);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(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(UInt64 left, UInt64 right, UInt64 result, [CallerMemberName] string method = "")
+ {
+ var isUnexpectedResult = false;
+
+ ulong expectedResult = 18446744073709551614; isUnexpectedResult = (expectedResult != result);
+
+ if (isUnexpectedResult)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Bmi2.X64)}.{nameof(Bmi2.X64.MultiplyNoFlags)}<UInt64>(UInt64, UInt64): MultiplyNoFlags failed:");
+ TestLibrary.TestFramework.LogInformation($" left: {left}");
+ TestLibrary.TestFramework.LogInformation($" right: {right}");
+ TestLibrary.TestFramework.LogInformation($" result: {result}");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Program.Bmi2.X64.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Program.Bmi2.X64.cs
index c0f8646319..c64728eef9 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Program.Bmi2.X64.cs
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/Program.Bmi2.X64.cs
@@ -14,6 +14,9 @@ namespace JIT.HardwareIntrinsics.X86
TestList = new Dictionary<string, Action>() {
["ParallelBitDeposit.UInt64"] = ParallelBitDepositUInt64,
["ParallelBitExtract.UInt64"] = ParallelBitExtractUInt64,
+ ["ZeroHighBits.UInt64"] = ZeroHighBitsUInt64,
+ ["MultiplyNoFlags.UInt64"] = MultiplyNoFlagsUInt64,
+ ["MultiplyNoFlags.UInt64.BinRes"] = MultiplyNoFlagsUInt64BinRes,
};
}
}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/ZeroHighBits.UInt64.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/ZeroHighBits.UInt64.cs
new file mode 100644
index 0000000000..9315651575
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2.X64/ZeroHighBits.UInt64.cs
@@ -0,0 +1,242 @@
+// 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 ZeroHighBitsUInt64()
+ {
+ var test = new ScalarBinaryOpTest__ZeroHighBitsUInt64();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.ReadUnaligned
+ test.RunBasicScenario_UnsafeRead();
+
+ // Validates calling via reflection works, using Unsafe.ReadUnaligned
+ test.RunReflectionScenario_UnsafeRead();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.ReadUnaligned
+ test.RunLclVarScenario_UnsafeRead();
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+ }
+ 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 ScalarBinaryOpTest__ZeroHighBitsUInt64
+ {
+ private struct TestStruct
+ {
+ public UInt64 _fld1;
+ public UInt64 _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ testStruct._fld1 = 0xFFFFFFFFFFFFFFFF;
+ testStruct._fld2 = 32;
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(ScalarBinaryOpTest__ZeroHighBitsUInt64 testClass)
+ {
+ var result = Bmi2.X64.ZeroHighBits(_fld1, _fld2);
+ testClass.ValidateResult(_fld1, _fld2, result);
+ }
+ }
+
+ private static UInt64 _data1;
+ private static UInt64 _data2;
+
+ private static UInt64 _clsVar1;
+ private static UInt64 _clsVar2;
+
+ private UInt64 _fld1;
+ private UInt64 _fld2;
+
+ static ScalarBinaryOpTest__ZeroHighBitsUInt64()
+ {
+ _clsVar1 = 0xFFFFFFFFFFFFFFFF;
+ _clsVar2 = 32;
+ }
+
+ public ScalarBinaryOpTest__ZeroHighBitsUInt64()
+ {
+ Succeeded = true;
+
+ _fld1 = 0xFFFFFFFFFFFFFFFF;
+ _fld2 = 32;
+
+ _data1 = 0xFFFFFFFFFFFFFFFF;
+ _data2 = 32;
+ }
+
+ public bool IsSupported => Bmi2.X64.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Bmi2.X64.ZeroHighBits(
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data2))
+ );
+
+ ValidateResult(_data1, _data2, result);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Bmi2.X64).GetMethod(nameof(Bmi2.X64.ZeroHighBits), new Type[] { typeof(UInt64), typeof(UInt64) })
+ .Invoke(null, new object[] {
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data2))
+ });
+
+ ValidateResult(_data1, _data2, (UInt64)result);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Bmi2.X64.ZeroHighBits(
+ _clsVar1,
+ _clsVar2
+ );
+
+ ValidateResult(_clsVar1, _clsVar2, result);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var data1 = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data1));
+ var data2 = Unsafe.ReadUnaligned<UInt64>(ref Unsafe.As<UInt64, byte>(ref _data2));
+ var result = Bmi2.X64.ZeroHighBits(data1, data2);
+
+ ValidateResult(data1, data2, result);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new ScalarBinaryOpTest__ZeroHighBitsUInt64();
+ var result = Bmi2.X64.ZeroHighBits(test._fld1, test._fld2);
+
+ ValidateResult(test._fld1, test._fld2, result);
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Bmi2.X64.ZeroHighBits(_fld1, _fld2);
+ ValidateResult(_fld1, _fld2, result);
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Bmi2.X64.ZeroHighBits(test._fld1, test._fld2);
+
+ ValidateResult(test._fld1, test._fld2, result);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(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(UInt64 left, UInt64 right, UInt64 result, [CallerMemberName] string method = "")
+ {
+ var isUnexpectedResult = false;
+
+ ulong expectedResult = 0xFFFFFFFF; isUnexpectedResult = (expectedResult != result);
+
+ if (isUnexpectedResult)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Bmi2.X64)}.{nameof(Bmi2.X64.ZeroHighBits)}<UInt64>(UInt64, UInt64): ZeroHighBits failed:");
+ TestLibrary.TestFramework.LogInformation($" left: {left}");
+ TestLibrary.TestFramework.LogInformation($" right: {right}");
+ TestLibrary.TestFramework.LogInformation($" result: {result}");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Bmi2_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Bmi2_r.csproj
index 2e2603f1d3..e935361ad6 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Bmi2_r.csproj
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Bmi2_r.csproj
@@ -29,6 +29,9 @@
<ItemGroup>
<Compile Include="ParallelBitDeposit.UInt32.cs" />
<Compile Include="ParallelBitExtract.UInt32.cs" />
+ <Compile Include="ZeroHighBits.UInt32.cs" />
+ <Compile Include="MultiplyNoFlags.UInt32.cs" />
+ <Compile Include="MultiplyNoFlags.UInt32.BinRes.cs" />
<Compile Include="Program.Bmi2.cs" />
<Compile Include="..\Shared\Program.cs" />
</ItemGroup>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Bmi2_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Bmi2_ro.csproj
index 952909b4b0..6f752553ba 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Bmi2_ro.csproj
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Bmi2_ro.csproj
@@ -29,6 +29,9 @@
<ItemGroup>
<Compile Include="ParallelBitDeposit.UInt32.cs" />
<Compile Include="ParallelBitExtract.UInt32.cs" />
+ <Compile Include="ZeroHighBits.UInt32.cs" />
+ <Compile Include="MultiplyNoFlags.UInt32.cs" />
+ <Compile Include="MultiplyNoFlags.UInt32.BinRes.cs" />
<Compile Include="Program.Bmi2.cs" />
<Compile Include="..\Shared\Program.cs" />
</ItemGroup>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/MultiplyNoFlags.UInt32.BinRes.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/MultiplyNoFlags.UInt32.BinRes.cs
new file mode 100644
index 0000000000..192fe6c788
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/MultiplyNoFlags.UInt32.BinRes.cs
@@ -0,0 +1,265 @@
+// 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.Reflection;
+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 MultiplyNoFlagsUInt32BinRes()
+ {
+ var test = new ScalarTernOpBinResTest__MultiplyNoFlagsUInt32();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.ReadUnaligned
+ test.RunBasicScenario_UnsafeRead();
+
+ // Validates calling via reflection works, using Unsafe.ReadUnaligned
+ test.RunReflectionScenario_UnsafeRead();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.ReadUnaligned
+ test.RunLclVarScenario_UnsafeRead();
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+ }
+ 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 ScalarTernOpBinResTest__MultiplyNoFlagsUInt32
+ {
+ private struct TestStruct
+ {
+ public UInt32 _fld1;
+ public UInt32 _fld2;
+ public UInt32 _fld3;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ testStruct._fld1 = UInt32.MaxValue;
+ testStruct._fld2 = UInt32.MaxValue;
+ testStruct._fld3 = 0;
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(ScalarTernOpBinResTest__MultiplyNoFlagsUInt32 testClass)
+ {
+ UInt32 buffer = 0;
+ var result = Bmi2.MultiplyNoFlags(_fld1, _fld2, &buffer);
+ testClass.ValidateResult(_fld1, _fld2, buffer, result);
+ }
+ }
+
+ private static UInt32 _data1;
+ private static UInt32 _data2;
+ private static UInt32 _data3;
+
+ private static UInt32 _clsVar1;
+ private static UInt32 _clsVar2;
+ private static UInt32 _clsVar3;
+
+ private UInt32 _fld1;
+ private UInt32 _fld2;
+ private UInt32 _fld3;
+
+ static ScalarTernOpBinResTest__MultiplyNoFlagsUInt32()
+ {
+ _clsVar1 = UInt32.MaxValue;
+ _clsVar2 = UInt32.MaxValue;
+ _clsVar3 = 0;
+ }
+
+ public ScalarTernOpBinResTest__MultiplyNoFlagsUInt32()
+ {
+ Succeeded = true;
+
+ _fld1 = UInt32.MaxValue;
+ _fld2 = UInt32.MaxValue;
+ _fld3 = 0;
+
+ _data1 = UInt32.MaxValue;
+ _data2 = UInt32.MaxValue;
+ _data3 = 0;
+ }
+
+ public bool IsSupported => Bmi2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ UInt32 buffer = 0;
+
+ var result = Bmi2.MultiplyNoFlags(
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data2)),
+ &buffer
+ );
+
+ ValidateResult(_data1, _data2, buffer, result);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ UInt32 buffer = 0;
+
+ var result = typeof(Bmi2).GetMethod(nameof(Bmi2.MultiplyNoFlags), new Type[] { typeof(UInt32), typeof(UInt32), typeof(UInt32*) })
+ .Invoke(null, new object[] {
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data2)),
+ Pointer.Box(&buffer, typeof(UInt32*))
+ });
+
+ ValidateResult(_data1, _data2, buffer, (UInt32)result);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+ UInt32 buffer = 0;
+ var result = Bmi2.MultiplyNoFlags(
+ _clsVar1,
+ _clsVar2,
+ &buffer
+ );
+
+ ValidateResult(_clsVar1, _clsVar2, buffer, result);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var data1 = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1));
+ var data2 = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data2));
+ var data3 = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data3));
+ var result = Bmi2.MultiplyNoFlags(data1, data2, &data3);
+
+ ValidateResult(data1, data2, data3, result);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ UInt32 buffer = 0;
+
+ var test = new ScalarTernOpBinResTest__MultiplyNoFlagsUInt32();
+ var result = Bmi2.MultiplyNoFlags(test._fld1, test._fld2, &buffer);
+
+ ValidateResult(test._fld1, test._fld2, buffer, result);
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ UInt32 buffer = 0;
+
+ var result = Bmi2.MultiplyNoFlags(_fld1, _fld2, &buffer);
+ ValidateResult(_fld1, _fld2, buffer, result);
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Bmi2.MultiplyNoFlags(test._fld1, test._fld2, &test._fld3);
+
+ ValidateResult(test._fld1, test._fld2, test._fld3, result);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(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(UInt32 op1, UInt32 op2, UInt32 lower, UInt32 higher, [CallerMemberName] string method = "")
+ {
+ var isUnexpectedResult = false;
+
+ uint expectedHigher = 4294967294, expectedLower = 1; isUnexpectedResult = (expectedHigher != higher) || (expectedLower != lower);
+
+ if (isUnexpectedResult)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Bmi2)}.{nameof(Bmi2.MultiplyNoFlags)}<UInt32>(UInt32, UInt32, UInt32): MultiplyNoFlags failed:");
+ TestLibrary.TestFramework.LogInformation($" op1: {op1}");
+ TestLibrary.TestFramework.LogInformation($" op2: {op2}");
+ TestLibrary.TestFramework.LogInformation($" lower: {lower}");
+ TestLibrary.TestFramework.LogInformation($"higher: {higher}");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/MultiplyNoFlags.UInt32.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/MultiplyNoFlags.UInt32.cs
new file mode 100644
index 0000000000..65b0b73b09
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/MultiplyNoFlags.UInt32.cs
@@ -0,0 +1,242 @@
+// 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 MultiplyNoFlagsUInt32()
+ {
+ var test = new ScalarBinaryOpTest__MultiplyNoFlagsUInt32();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.ReadUnaligned
+ test.RunBasicScenario_UnsafeRead();
+
+ // Validates calling via reflection works, using Unsafe.ReadUnaligned
+ test.RunReflectionScenario_UnsafeRead();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.ReadUnaligned
+ test.RunLclVarScenario_UnsafeRead();
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+ }
+ 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 ScalarBinaryOpTest__MultiplyNoFlagsUInt32
+ {
+ private struct TestStruct
+ {
+ public UInt32 _fld1;
+ public UInt32 _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ testStruct._fld1 = UInt32.MaxValue;
+ testStruct._fld2 = UInt32.MaxValue;
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(ScalarBinaryOpTest__MultiplyNoFlagsUInt32 testClass)
+ {
+ var result = Bmi2.MultiplyNoFlags(_fld1, _fld2);
+ testClass.ValidateResult(_fld1, _fld2, result);
+ }
+ }
+
+ private static UInt32 _data1;
+ private static UInt32 _data2;
+
+ private static UInt32 _clsVar1;
+ private static UInt32 _clsVar2;
+
+ private UInt32 _fld1;
+ private UInt32 _fld2;
+
+ static ScalarBinaryOpTest__MultiplyNoFlagsUInt32()
+ {
+ _clsVar1 = UInt32.MaxValue;
+ _clsVar2 = UInt32.MaxValue;
+ }
+
+ public ScalarBinaryOpTest__MultiplyNoFlagsUInt32()
+ {
+ Succeeded = true;
+
+ _fld1 = UInt32.MaxValue;
+ _fld2 = UInt32.MaxValue;
+
+ _data1 = UInt32.MaxValue;
+ _data2 = UInt32.MaxValue;
+ }
+
+ public bool IsSupported => Bmi2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Bmi2.MultiplyNoFlags(
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data2))
+ );
+
+ ValidateResult(_data1, _data2, result);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Bmi2).GetMethod(nameof(Bmi2.MultiplyNoFlags), new Type[] { typeof(UInt32), typeof(UInt32) })
+ .Invoke(null, new object[] {
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data2))
+ });
+
+ ValidateResult(_data1, _data2, (UInt32)result);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Bmi2.MultiplyNoFlags(
+ _clsVar1,
+ _clsVar2
+ );
+
+ ValidateResult(_clsVar1, _clsVar2, result);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var data1 = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1));
+ var data2 = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data2));
+ var result = Bmi2.MultiplyNoFlags(data1, data2);
+
+ ValidateResult(data1, data2, result);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new ScalarBinaryOpTest__MultiplyNoFlagsUInt32();
+ var result = Bmi2.MultiplyNoFlags(test._fld1, test._fld2);
+
+ ValidateResult(test._fld1, test._fld2, result);
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Bmi2.MultiplyNoFlags(_fld1, _fld2);
+ ValidateResult(_fld1, _fld2, result);
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Bmi2.MultiplyNoFlags(test._fld1, test._fld2);
+
+ ValidateResult(test._fld1, test._fld2, result);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(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(UInt32 left, UInt32 right, UInt32 result, [CallerMemberName] string method = "")
+ {
+ var isUnexpectedResult = false;
+
+ uint expectedResult = 4294967294; isUnexpectedResult = (expectedResult != result);
+
+ if (isUnexpectedResult)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Bmi2)}.{nameof(Bmi2.MultiplyNoFlags)}<UInt32>(UInt32, UInt32): MultiplyNoFlags failed:");
+ TestLibrary.TestFramework.LogInformation($" left: {left}");
+ TestLibrary.TestFramework.LogInformation($" right: {right}");
+ TestLibrary.TestFramework.LogInformation($" result: {result}");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Program.Bmi2.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Program.Bmi2.cs
index 31300b1bd9..f8a5d07cca 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Program.Bmi2.cs
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/Program.Bmi2.cs
@@ -14,6 +14,9 @@ namespace JIT.HardwareIntrinsics.X86
TestList = new Dictionary<string, Action>() {
["ParallelBitDeposit.UInt32"] = ParallelBitDepositUInt32,
["ParallelBitExtract.UInt32"] = ParallelBitExtractUInt32,
+ ["ZeroHighBits.UInt32"] = ZeroHighBitsUInt32,
+ ["MultiplyNoFlags.UInt32"] = MultiplyNoFlagsUInt32,
+ ["MultiplyNoFlags.UInt32.BinRes"] = MultiplyNoFlagsUInt32BinRes,
};
}
}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/ZeroHighBits.UInt32.cs b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/ZeroHighBits.UInt32.cs
new file mode 100644
index 0000000000..dc050093d8
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Bmi2/ZeroHighBits.UInt32.cs
@@ -0,0 +1,242 @@
+// 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 ZeroHighBitsUInt32()
+ {
+ var test = new ScalarBinaryOpTest__ZeroHighBitsUInt32();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.ReadUnaligned
+ test.RunBasicScenario_UnsafeRead();
+
+ // Validates calling via reflection works, using Unsafe.ReadUnaligned
+ test.RunReflectionScenario_UnsafeRead();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.ReadUnaligned
+ test.RunLclVarScenario_UnsafeRead();
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+ }
+ 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 ScalarBinaryOpTest__ZeroHighBitsUInt32
+ {
+ private struct TestStruct
+ {
+ public UInt32 _fld1;
+ public UInt32 _fld2;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ testStruct._fld1 = 0xFFFFFFFF;
+ testStruct._fld2 = 16;
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(ScalarBinaryOpTest__ZeroHighBitsUInt32 testClass)
+ {
+ var result = Bmi2.ZeroHighBits(_fld1, _fld2);
+ testClass.ValidateResult(_fld1, _fld2, result);
+ }
+ }
+
+ private static UInt32 _data1;
+ private static UInt32 _data2;
+
+ private static UInt32 _clsVar1;
+ private static UInt32 _clsVar2;
+
+ private UInt32 _fld1;
+ private UInt32 _fld2;
+
+ static ScalarBinaryOpTest__ZeroHighBitsUInt32()
+ {
+ _clsVar1 = 0xFFFFFFFF;
+ _clsVar2 = 16;
+ }
+
+ public ScalarBinaryOpTest__ZeroHighBitsUInt32()
+ {
+ Succeeded = true;
+
+ _fld1 = 0xFFFFFFFF;
+ _fld2 = 16;
+
+ _data1 = 0xFFFFFFFF;
+ _data2 = 16;
+ }
+
+ public bool IsSupported => Bmi2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = Bmi2.ZeroHighBits(
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data2))
+ );
+
+ ValidateResult(_data1, _data2, result);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof(Bmi2).GetMethod(nameof(Bmi2.ZeroHighBits), new Type[] { typeof(UInt32), typeof(UInt32) })
+ .Invoke(null, new object[] {
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data2))
+ });
+
+ ValidateResult(_data1, _data2, (UInt32)result);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = Bmi2.ZeroHighBits(
+ _clsVar1,
+ _clsVar2
+ );
+
+ ValidateResult(_clsVar1, _clsVar2, result);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var data1 = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data1));
+ var data2 = Unsafe.ReadUnaligned<UInt32>(ref Unsafe.As<UInt32, byte>(ref _data2));
+ var result = Bmi2.ZeroHighBits(data1, data2);
+
+ ValidateResult(data1, data2, result);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new ScalarBinaryOpTest__ZeroHighBitsUInt32();
+ var result = Bmi2.ZeroHighBits(test._fld1, test._fld2);
+
+ ValidateResult(test._fld1, test._fld2, result);
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = Bmi2.ZeroHighBits(_fld1, _fld2);
+ ValidateResult(_fld1, _fld2, result);
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = Bmi2.ZeroHighBits(test._fld1, test._fld2);
+
+ ValidateResult(test._fld1, test._fld2, result);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(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(UInt32 left, UInt32 right, UInt32 result, [CallerMemberName] string method = "")
+ {
+ var isUnexpectedResult = false;
+
+ uint expectedResult = 0xFFFF; isUnexpectedResult = (expectedResult != result);
+
+ if (isUnexpectedResult)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof(Bmi2)}.{nameof(Bmi2.ZeroHighBits)}<UInt32>(UInt32, UInt32): ZeroHighBits failed:");
+ TestLibrary.TestFramework.LogInformation($" left: {left}");
+ TestLibrary.TestFramework.LogInformation($" right: {right}");
+ TestLibrary.TestFramework.LogInformation($" result: {result}");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx
index ea742f90b2..2b5ecfa1f8 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx
@@ -1020,20 +1020,24 @@ private static readonly (string templateFileName, Dictionary<string, string> tem
private static readonly (string templateFileName, Dictionary<string, string> templateData)[] Bmi1Inputs = new []
{
- ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "AndNot", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "isUnexpectedResult = ((~left & right) != result);" }),
- ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "ExtractLowestSetBit", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "isUnexpectedResult = ((unchecked((uint)(-(int)data)) & data) != result);" }),
- ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "GetMaskUpToLowestSetBit", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "isUnexpectedResult = (((data - 1) ^ data) != result);" }),
- ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "ResetLowestSetBit", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "isUnexpectedResult = (((data - 1) & data) != result);" }),
- ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "TrailingZeroCount", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "uint expectedResult = 0; for (int index = 0; ((data >> index) & 1) == 0; index++) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }),
+ ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "AndNot", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "isUnexpectedResult = ((~left & right) != result);" }),
+ ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "ExtractLowestSetBit", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "isUnexpectedResult = ((unchecked((uint)(-(int)data)) & data) != result);" }),
+ ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "GetMaskUpToLowestSetBit", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "isUnexpectedResult = (((data - 1) ^ data) != result);" }),
+ ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "ResetLowestSetBit", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "isUnexpectedResult = (((data - 1) & data) != result);" }),
+ ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "TrailingZeroCount", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = "uint expectedResult = 0; for (int index = 0; ((data >> index) & 1) == 0; index++) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }),
+ ("ScalarTernOpTest.template",new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "BitFieldExtract", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "Byte", ["Op3BaseType"] = "Byte", ["NextValueOp1"] = "0x1E000000", ["NextValueOp2"] = "25", ["NextValueOp3"] = "4", ["ValidateResult"] = "uint expectedResult = 15; isUnexpectedResult = (expectedResult != result);" }),
+ ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1", ["Method"] = "BitFieldExtract", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt16", ["NextValueOp1"] = "0x1E000000", ["NextValueOp2"] = "0x0419", ["ValidateResult"] = "uint expectedResult = 15; isUnexpectedResult = (expectedResult != result);" }),
};
private static readonly (string templateFileName, Dictionary<string, string> templateData)[] Bmi1X64Inputs = new []
{
- ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1.X64", ["Method"] = "AndNot", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "isUnexpectedResult = ((~left & right) != result);" }),
- ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1.X64", ["Method"] = "ExtractLowestSetBit", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "isUnexpectedResult = ((unchecked((ulong)(-(long)data)) & data) != result);" }),
- ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1.X64", ["Method"] = "GetMaskUpToLowestSetBit", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "isUnexpectedResult = (((data - 1) ^ data) != result);" }),
- ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1.X64", ["Method"] = "ResetLowestSetBit", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "isUnexpectedResult = (((data - 1) & data) != result);" }),
- ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1.X64", ["Method"] = "TrailingZeroCount", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "ulong expectedResult = 0; for (int index = 0; ((data >> index) & 1) == 0; index++) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }),
+ ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1.X64", ["Method"] = "AndNot", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "isUnexpectedResult = ((~left & right) != result);" }),
+ ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1.X64", ["Method"] = "ExtractLowestSetBit", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "isUnexpectedResult = ((unchecked((ulong)(-(long)data)) & data) != result);" }),
+ ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1.X64", ["Method"] = "GetMaskUpToLowestSetBit", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "isUnexpectedResult = (((data - 1) ^ data) != result);" }),
+ ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1.X64", ["Method"] = "ResetLowestSetBit", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "isUnexpectedResult = (((data - 1) & data) != result);" }),
+ ("ScalarUnOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1.X64", ["Method"] = "TrailingZeroCount", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = "ulong expectedResult = 0; for (int index = 0; ((data >> index) & 1) == 0; index++) { expectedResult++; } isUnexpectedResult = (expectedResult != result);" }),
+ ("ScalarTernOpTest.template",new Dictionary<string, string> { ["Isa"] = "Bmi1.X64", ["Method"] = "BitFieldExtract", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "Byte",["Op3BaseType"] = "Byte", ["NextValueOp1"] = "0x1E00000000000000", ["NextValueOp2"] = "57", ["NextValueOp3"] = "4", ["ValidateResult"] = "ulong expectedResult = 15; isUnexpectedResult = (expectedResult != result);" }),
+ ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi1.X64", ["Method"] = "BitFieldExtract", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt16", ["NextValueOp1"] = "0x1E00000000000000", ["NextValueOp2"] = "0x0439", ["ValidateResult"] = "ulong expectedResult = 15; isUnexpectedResult = (expectedResult != result);" }),
};
private static readonly (string templateFileName, Dictionary<string, string> templateData)[] AesInputs = new []
@@ -1145,14 +1149,20 @@ isUnexpectedResult = (dest != result);
private static readonly (string templateFileName, Dictionary<string, string> templateData)[] Bmi2Inputs = new []
{
- ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2", ["Method"] = "ParallelBitDeposit", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = ValidateBmi2ParallelBitDepositUInt32 }),
- ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2", ["Method"] = "ParallelBitExtract", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = ValidateBmi2ParallelBitExtractUInt32 }),
+ ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2", ["Method"] = "ParallelBitDeposit", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = ValidateBmi2ParallelBitDepositUInt32 }),
+ ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2", ["Method"] = "ParallelBitExtract", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateResult"] = ValidateBmi2ParallelBitExtractUInt32 }),
+ ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2", ["Method"] = "ZeroHighBits", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "0xFFFFFFFF", ["NextValueOp2"] = "16", ["ValidateResult"] = "uint expectedResult = 0xFFFF; isUnexpectedResult = (expectedResult != result);" }),
+ ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2", ["Method"] = "MultiplyNoFlags", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["NextValueOp1"] = "UInt32.MaxValue", ["NextValueOp2"] = "UInt32.MaxValue", ["ValidateResult"] = "uint expectedResult = 4294967294; isUnexpectedResult = (expectedResult != result);" }),
+ ("ScalarTernOpBinResTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2", ["Method"] = "MultiplyNoFlags", ["RetBaseType"] = "UInt32", ["Op1BaseType"] = "UInt32", ["Op2BaseType"] = "UInt32", ["Op3BaseType"] = "UInt32", ["NextValueOp1"] = "UInt32.MaxValue", ["NextValueOp2"] = "UInt32.MaxValue", ["NextValueOp3"] = "0", ["ValidateResult"] = "uint expectedHigher = 4294967294, expectedLower = 1; isUnexpectedResult = (expectedHigher != higher) || (expectedLower != lower);" }),
};
private static readonly (string templateFileName, Dictionary<string, string> templateData)[] Bmi2X64Inputs = new []
{
- ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2.X64", ["Method"] = "ParallelBitDeposit", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = ValidateBmi2ParallelBitDepositUInt64 }),
- ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2.X64", ["Method"] = "ParallelBitExtract", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = ValidateBmi2ParallelBitExtractUInt64 }),
+ ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2.X64", ["Method"] = "ParallelBitDeposit", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = ValidateBmi2ParallelBitDepositUInt64 }),
+ ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2.X64", ["Method"] = "ParallelBitExtract", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt64()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt64()", ["ValidateResult"] = ValidateBmi2ParallelBitExtractUInt64 }),
+ ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2.X64", ["Method"] = "ZeroHighBits", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "0xFFFFFFFFFFFFFFFF", ["NextValueOp2"] = "32", ["ValidateResult"] = "ulong expectedResult = 0xFFFFFFFF; isUnexpectedResult = (expectedResult != result);" }),
+ ("ScalarBinOpTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2.X64", ["Method"] = "MultiplyNoFlags", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["NextValueOp1"] = "UInt64.MaxValue", ["NextValueOp2"] = "UInt64.MaxValue", ["ValidateResult"] = "ulong expectedResult = 18446744073709551614; isUnexpectedResult = (expectedResult != result);" }),
+ ("ScalarTernOpBinResTest.template", new Dictionary<string, string> { ["Isa"] = "Bmi2.X64", ["Method"] = "MultiplyNoFlags", ["RetBaseType"] = "UInt64", ["Op1BaseType"] = "UInt64", ["Op2BaseType"] = "UInt64", ["Op3BaseType"] = "UInt64", ["NextValueOp1"] = "UInt64.MaxValue", ["NextValueOp2"] = "UInt64.MaxValue", ["NextValueOp3"] = "0", ["ValidateResult"] = "ulong expectedHigher = 18446744073709551614, expectedLower = 1; isUnexpectedResult = (expectedHigher != higher) || (expectedLower != lower);" }),
};
private static void ProcessInputs(string groupName, (string templateFileName, Dictionary<string, string> templateData)[] inputs)
@@ -1226,6 +1236,16 @@ private static void ProcessInput(StreamWriter testListFile, string groupName, (s
testName += ".Store";
suffix += "Store";
}
+ else if (input.templateFileName == "ScalarTernOpTest.template")
+ {
+ testName += ".3Op";
+ suffix += "3Op";
+ }
+ else if (input.templateFileName == "ScalarTernOpBinResTest.template")
+ {
+ testName += ".BinRes";
+ suffix += "BinRes";
+ }
if (input.templateFileName == "SimpleUnOpConvTest.template" || input.templateFileName == "SimdScalarUnOpConvTest.template" )
{
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarBinOpTest.template b/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarBinOpTest.template
index ed05de44a8..04cecabc97 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarBinOpTest.template
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarBinOpTest.template
@@ -158,7 +158,7 @@ namespace JIT.HardwareIntrinsics.X86
TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
var data1 = Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1));
- var data2 = Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data2));
+ var data2 = Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2));
var result = {Isa}.{Method}(data1, data2);
ValidateResult(data1, data2, result);
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarTernOpBinResTest.template b/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarTernOpBinResTest.template
new file mode 100644
index 0000000000..a958777bde
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarTernOpBinResTest.template
@@ -0,0 +1,265 @@
+// 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.Reflection;
+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 {Method}{RetBaseType}BinRes()
+ {
+ var test = new ScalarTernOpBinResTest__{Method}{RetBaseType}();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.ReadUnaligned
+ test.RunBasicScenario_UnsafeRead();
+
+ // Validates calling via reflection works, using Unsafe.ReadUnaligned
+ test.RunReflectionScenario_UnsafeRead();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.ReadUnaligned
+ test.RunLclVarScenario_UnsafeRead();
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+ }
+ 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 ScalarTernOpBinResTest__{Method}{RetBaseType}
+ {
+ private struct TestStruct
+ {
+ public {Op1BaseType} _fld1;
+ public {Op2BaseType} _fld2;
+ public {Op3BaseType} _fld3;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ testStruct._fld1 = {NextValueOp1};
+ testStruct._fld2 = {NextValueOp2};
+ testStruct._fld3 = {NextValueOp3};
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(ScalarTernOpBinResTest__{Method}{RetBaseType} testClass)
+ {
+ {Op3BaseType} buffer = 0;
+ var result = {Isa}.{Method}(_fld1, _fld2, &buffer);
+ testClass.ValidateResult(_fld1, _fld2, buffer, result);
+ }
+ }
+
+ private static {Op1BaseType} _data1;
+ private static {Op2BaseType} _data2;
+ private static {Op3BaseType} _data3;
+
+ private static {Op1BaseType} _clsVar1;
+ private static {Op2BaseType} _clsVar2;
+ private static {Op3BaseType} _clsVar3;
+
+ private {Op1BaseType} _fld1;
+ private {Op2BaseType} _fld2;
+ private {Op3BaseType} _fld3;
+
+ static ScalarTernOpBinResTest__{Method}{RetBaseType}()
+ {
+ _clsVar1 = {NextValueOp1};
+ _clsVar2 = {NextValueOp2};
+ _clsVar3 = {NextValueOp3};
+ }
+
+ public ScalarTernOpBinResTest__{Method}{RetBaseType}()
+ {
+ Succeeded = true;
+
+ _fld1 = {NextValueOp1};
+ _fld2 = {NextValueOp2};
+ _fld3 = {NextValueOp3};
+
+ _data1 = {NextValueOp1};
+ _data2 = {NextValueOp2};
+ _data3 = {NextValueOp3};
+ }
+
+ public bool IsSupported => {Isa}.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ {Op3BaseType} buffer = 0;
+
+ var result = {Isa}.{Method}(
+ Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2)),
+ &buffer
+ );
+
+ ValidateResult(_data1, _data2, buffer, result);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ {Op3BaseType} buffer = 0;
+
+ var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1BaseType}), typeof({Op2BaseType}), typeof({Op3BaseType}*) })
+ .Invoke(null, new object[] {
+ Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2)),
+ Pointer.Box(&buffer, typeof({Op3BaseType}*))
+ });
+
+ ValidateResult(_data1, _data2, buffer, ({RetBaseType})result);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+ {Op3BaseType} buffer = 0;
+ var result = {Isa}.{Method}(
+ _clsVar1,
+ _clsVar2,
+ &buffer
+ );
+
+ ValidateResult(_clsVar1, _clsVar2, buffer, result);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var data1 = Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1));
+ var data2 = Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2));
+ var data3 = Unsafe.ReadUnaligned<{Op3BaseType}>(ref Unsafe.As<{Op3BaseType}, byte>(ref _data3));
+ var result = {Isa}.{Method}(data1, data2, &data3);
+
+ ValidateResult(data1, data2, data3, result);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ {Op3BaseType} buffer = 0;
+
+ var test = new ScalarTernOpBinResTest__{Method}{RetBaseType}();
+ var result = {Isa}.{Method}(test._fld1, test._fld2, &buffer);
+
+ ValidateResult(test._fld1, test._fld2, buffer, result);
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ {Op3BaseType} buffer = 0;
+
+ var result = {Isa}.{Method}(_fld1, _fld2, &buffer);
+ ValidateResult(_fld1, _fld2, buffer, result);
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = {Isa}.{Method}(test._fld1, test._fld2, &test._fld3);
+
+ ValidateResult(test._fld1, test._fld2, test._fld3, result);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(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({Op1BaseType} op1, {Op2BaseType} op2, {Op3BaseType} lower, {RetBaseType} higher, [CallerMemberName] string method = "")
+ {
+ var isUnexpectedResult = false;
+
+ {ValidateResult}
+
+ if (isUnexpectedResult)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1BaseType}, {Op2BaseType}, {Op3BaseType}): {Method} failed:");
+ TestLibrary.TestFramework.LogInformation($" op1: {op1}");
+ TestLibrary.TestFramework.LogInformation($" op2: {op2}");
+ TestLibrary.TestFramework.LogInformation($" lower: {lower}");
+ TestLibrary.TestFramework.LogInformation($"higher: {higher}");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarTernOpTest.template b/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarTernOpTest.template
new file mode 100644
index 0000000000..a80a93ee63
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/ScalarTernOpTest.template
@@ -0,0 +1,255 @@
+// 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 {Method}{RetBaseType}3Op()
+ {
+ var test = new ScalarTernOpTest__{Method}{RetBaseType}();
+
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.ReadUnaligned
+ test.RunBasicScenario_UnsafeRead();
+
+ // Validates calling via reflection works, using Unsafe.ReadUnaligned
+ test.RunReflectionScenario_UnsafeRead();
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.ReadUnaligned
+ test.RunLclVarScenario_UnsafeRead();
+
+ // Validates passing the field of a local class works
+ test.RunClassLclFldScenario();
+
+ // Validates passing an instance member of a class works
+ test.RunClassFldScenario();
+
+ // Validates passing the field of a local struct works
+ test.RunStructLclFldScenario();
+
+ // Validates passing an instance member of a struct works
+ test.RunStructFldScenario();
+ }
+ 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 ScalarTernOpTest__{Method}{RetBaseType}
+ {
+ private struct TestStruct
+ {
+ public {Op1BaseType} _fld1;
+ public {Op2BaseType} _fld2;
+ public {Op3BaseType} _fld3;
+
+ public static TestStruct Create()
+ {
+ var testStruct = new TestStruct();
+
+ testStruct._fld1 = {NextValueOp1};
+ testStruct._fld2 = {NextValueOp2};
+ testStruct._fld3 = {NextValueOp3};
+
+ return testStruct;
+ }
+
+ public void RunStructFldScenario(ScalarTernOpTest__{Method}{RetBaseType} testClass)
+ {
+ var result = {Isa}.{Method}(_fld1, _fld2, _fld3);
+ testClass.ValidateResult(_fld1, _fld2, _fld3, result);
+ }
+ }
+
+ private static {Op1BaseType} _data1;
+ private static {Op2BaseType} _data2;
+ private static {Op3BaseType} _data3;
+
+ private static {Op1BaseType} _clsVar1;
+ private static {Op2BaseType} _clsVar2;
+ private static {Op3BaseType} _clsVar3;
+
+ private {Op1BaseType} _fld1;
+ private {Op2BaseType} _fld2;
+ private {Op3BaseType} _fld3;
+
+ static ScalarTernOpTest__{Method}{RetBaseType}()
+ {
+ _clsVar1 = {NextValueOp1};
+ _clsVar2 = {NextValueOp2};
+ _clsVar3 = {NextValueOp3};
+ }
+
+ public ScalarTernOpTest__{Method}{RetBaseType}()
+ {
+ Succeeded = true;
+
+ _fld1 = {NextValueOp1};
+ _fld2 = {NextValueOp2};
+ _fld3 = {NextValueOp3};
+
+ _data1 = {NextValueOp1};
+ _data2 = {NextValueOp2};
+ _data3 = {NextValueOp3};
+ }
+
+ public bool IsSupported => {Isa}.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead));
+
+ var result = {Isa}.{Method}(
+ Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2)),
+ Unsafe.ReadUnaligned<{Op3BaseType}>(ref Unsafe.As<{Op3BaseType}, byte>(ref _data3))
+ );
+
+ ValidateResult(_data1, _data2, _data3, result);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead));
+
+ var result = typeof({Isa}).GetMethod(nameof({Isa}.{Method}), new Type[] { typeof({Op1BaseType}), typeof({Op2BaseType}), typeof({Op3BaseType}) })
+ .Invoke(null, new object[] {
+ Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1)),
+ Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2)),
+ Unsafe.ReadUnaligned<{Op3BaseType}>(ref Unsafe.As<{Op3BaseType}, byte>(ref _data3))
+ });
+
+ ValidateResult(_data1, _data2, _data3, ({RetBaseType})result);
+ }
+
+ public void RunClsVarScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario));
+
+ var result = {Isa}.{Method}(
+ _clsVar1,
+ _clsVar2,
+ _clsVar3
+ );
+
+ ValidateResult(_clsVar1, _clsVar2, _clsVar3, result);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunLclVarScenario_UnsafeRead));
+
+ var data1 = Unsafe.ReadUnaligned<{Op1BaseType}>(ref Unsafe.As<{Op1BaseType}, byte>(ref _data1));
+ var data2 = Unsafe.ReadUnaligned<{Op2BaseType}>(ref Unsafe.As<{Op2BaseType}, byte>(ref _data2));
+ var data3 = Unsafe.ReadUnaligned<{Op3BaseType}>(ref Unsafe.As<{Op3BaseType}, byte>(ref _data3));
+ var result = {Isa}.{Method}(data1, data2, data3);
+
+ ValidateResult(data1, data2, data3, result);
+ }
+
+ public void RunClassLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario));
+
+ var test = new ScalarTernOpTest__{Method}{RetBaseType}();
+ var result = {Isa}.{Method}(test._fld1, test._fld2, test._fld3);
+
+ ValidateResult(test._fld1, test._fld2, test._fld3, result);
+ }
+
+ public void RunClassFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario));
+
+ var result = {Isa}.{Method}(_fld1, _fld2, _fld3);
+ ValidateResult(_fld1, _fld2, _fld3, result);
+ }
+
+ public void RunStructLclFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario));
+
+ var test = TestStruct.Create();
+ var result = {Isa}.{Method}(test._fld1, test._fld2, test._fld3);
+
+ ValidateResult(test._fld1, test._fld2, test._fld3, result);
+ }
+
+ public void RunStructFldScenario()
+ {
+ TestLibrary.TestFramework.BeginScenario(nameof(RunStructFldScenario));
+
+ var test = TestStruct.Create();
+ test.RunStructFldScenario(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({Op1BaseType} op1, {Op2BaseType} op2, {Op3BaseType} op3, {RetBaseType} result, [CallerMemberName] string method = "")
+ {
+ var isUnexpectedResult = false;
+
+ {ValidateResult}
+
+ if (isUnexpectedResult)
+ {
+ TestLibrary.TestFramework.LogInformation($"{nameof({Isa})}.{nameof({Isa}.{Method})}<{RetBaseType}>({Op1BaseType}, {Op2BaseType}, {Op3BaseType}): {Method} failed:");
+ TestLibrary.TestFramework.LogInformation($" op1: {op1}");
+ TestLibrary.TestFramework.LogInformation($" op2: {op2}");
+ TestLibrary.TestFramework.LogInformation($" op3: {op3}");
+ TestLibrary.TestFramework.LogInformation($" result: {result}");
+ TestLibrary.TestFramework.LogInformation(string.Empty);
+
+ Succeeded = false;
+ }
+ }
+ }
+}