summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jit/compiler.h9
-rw-r--r--src/jit/emitxarch.cpp39
-rw-r--r--src/jit/hwintrinsiccodegenxarch.cpp77
-rw-r--r--src/jit/hwintrinsiclistxarch.h130
-rw-r--r--src/jit/hwintrinsicxarch.cpp202
-rw-r--r--src/jit/instrsxarch.h7
-rw-r--r--src/jit/lsraxarch.cpp14
-rw-r--r--src/jit/namedintrinsiclist.h21
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Shared/ExtractScalarTest.template309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx41
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Shared/InsertScalarTest.template321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.1.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.129.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.1.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.129.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.1.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.129.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.1.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.129.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs8
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj8
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj8
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.1.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.129.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.1.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.129.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.1.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.129.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.1.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.129.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.1.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.129.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.1.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.129.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.1.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.129.cs309
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.1.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.129.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.1.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.129.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.1.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.129.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.1.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.129.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.0.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.217.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.1.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.129.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.1.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.129.cs321
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Program.Sse41.cs28
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_r.csproj28
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_ro.csproj28
53 files changed, 12372 insertions, 246 deletions
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index 7b9313ae54..7bee3bfcdd 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -3059,14 +3059,6 @@ protected:
CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig,
bool mustExpand);
- GenTree* impSSE3Intrinsic(NamedIntrinsic intrinsic,
- CORINFO_METHOD_HANDLE method,
- CORINFO_SIG_INFO* sig,
- bool mustExpand);
- GenTree* impSSSE3Intrinsic(NamedIntrinsic intrinsic,
- CORINFO_METHOD_HANDLE method,
- CORINFO_SIG_INFO* sig,
- bool mustExpand);
GenTree* impSSE41Intrinsic(NamedIntrinsic intrinsic,
CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig,
@@ -3125,6 +3117,7 @@ protected:
GenTree* impNonConstFallback(NamedIntrinsic intrinsic, var_types simdType, var_types baseType);
static bool isImmHWIntrinsic(NamedIntrinsic intrinsic, GenTree* lastOp);
GenTree* addRangeCheckIfNeeded(NamedIntrinsic intrinsic, GenTree* lastOp, bool mustExpand);
+ bool hwIntrinsicSignatureTypeSupported(var_types retType, CORINFO_SIG_INFO* sig, HWIntrinsicFlag flags);
#endif // _TARGET_XARCH_
#ifdef _TARGET_ARM64_
InstructionSet lookupHWIntrinsicISA(const char* className);
diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp
index 64a76357c1..4ffe342c99 100644
--- a/src/jit/emitxarch.cpp
+++ b/src/jit/emitxarch.cpp
@@ -155,7 +155,10 @@ bool emitter::IsDstDstSrcAVXInstruction(instruction ins)
case INS_phsubd:
case INS_phsubsw:
case INS_phsubw:
+ case INS_pinsrb:
case INS_pinsrw:
+ case INS_pinsrd:
+ case INS_pinsrq:
case INS_pmaddubsw:
case INS_pmaddwd:
case INS_pmaxsb:
@@ -383,9 +386,16 @@ bool TakesRexWPrefix(instruction ins, emitAttr attr)
// size specification (128 vs. 256 bits) and the operand size specification (32 vs. 64 bits), where both are
// required, the instruction must be created with the register size attribute (EA_16BYTE or EA_32BYTE),
// and here we must special case these by the opcode.
- if (ins == INS_vpermq || ins == INS_vpsrlvq || ins == INS_vpsllvq)
+ switch (ins)
{
- return true;
+ case INS_vpermq:
+ case INS_vpsrlvq:
+ case INS_vpsllvq:
+ case INS_pinsrq:
+ case INS_pextrq:
+ return true;
+ default:
+ break;
}
#endif // !LEGACY_BACKEND
#ifdef _TARGET_AMD64_
@@ -1084,7 +1094,7 @@ bool emitter::emitInsCanOnlyWriteSSE2OrAVXReg(instrDesc* id)
if (!IsSSEOrAVXInstruction(ins) || ins == INS_mov_xmm2i || ins == INS_cvttsd2si
#ifndef LEGACY_BACKEND
|| ins == INS_cvttss2si || ins == INS_cvtsd2si || ins == INS_cvtss2si || ins == INS_pmovmskb ||
- ins == INS_pextrw
+ ins == INS_pextrw || ins == INS_pextrb || ins == INS_pextrd || ins == INS_pextrq || ins == INS_extractps
#endif // !LEGACY_BACKEND
)
{
@@ -4034,6 +4044,12 @@ void emitter::emitIns_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regN
sz += emitGetRexPrefixSize(ins);
}
+ if ((ins == INS_pextrq || ins == INS_pinsrq) && !UseVEXEncoding())
+ {
+ assert(UseSSE4());
+ sz += 1;
+ }
+
id->idIns(ins);
id->idInsFmt(IF_RRW_RRW_CNS);
id->idReg1(reg1);
@@ -5519,11 +5535,26 @@ static bool isSseShift(instruction ins)
}
}
+static bool isSSEExtract(instruction ins)
+{
+ switch (ins)
+ {
+ case INS_pextrb:
+ case INS_pextrw:
+ case INS_pextrd:
+ case INS_pextrq:
+ case INS_extractps:
+ return true;
+ default:
+ return false;
+ }
+}
+
void emitter::emitIns_SIMD_R_R_I(instruction ins, emitAttr attr, regNumber reg, regNumber reg1, int ival)
{
// TODO-XARCH refactoring emitIns_R_R_I to handle SSE2/AVX2 shift as well as emitIns_R_I
bool isShift = isSseShift(ins);
- if (UseVEXEncoding() && !isShift)
+ if (isSSEExtract(ins) || (UseVEXEncoding() && !isShift))
{
emitIns_R_R_I(ins, attr, reg, reg1, ival);
}
diff --git a/src/jit/hwintrinsiccodegenxarch.cpp b/src/jit/hwintrinsiccodegenxarch.cpp
index eb7a9134ce..2f0e5f8c41 100644
--- a/src/jit/hwintrinsiccodegenxarch.cpp
+++ b/src/jit/hwintrinsiccodegenxarch.cpp
@@ -36,10 +36,10 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
static bool genIsTableDrivenHWIntrinsic(HWIntrinsicCategory category, HWIntrinsicFlag flags)
{
// TODO - make more categories to the table-driven framework
- // HW_Category_Helper and HW_Flag_MultiIns usually need manual codegen
+ // HW_Category_Helper and HW_Flag_MultiIns/HW_Flag_SpecialCodeGen usually need manual codegen
const bool tableDrivenCategory =
category != HW_Category_Special && category != HW_Category_Scalar && category != HW_Category_Helper;
- const bool tableDrivenFlag = (flags & HW_Flag_MultiIns) == 0;
+ const bool tableDrivenFlag = (flags & (HW_Flag_MultiIns | HW_Flag_SpecialCodeGen)) == 0;
return tableDrivenCategory && tableDrivenFlag;
}
@@ -119,6 +119,11 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
}
else if (Compiler::isImmHWIntrinsic(intrinsicID, op2))
{
+ if (intrinsicID == NI_SSE2_Extract)
+ {
+ // extract instructions return to GP-registers, so it needs int size as the emitsize
+ simdSize = emitTypeSize(TYP_INT);
+ }
auto emitSwCase = [&](unsigned i) {
emit->emitIns_SIMD_R_R_I(ins, simdSize, targetReg, op1Reg, (int)i);
};
@@ -605,17 +610,6 @@ void CodeGen::genSSEIntrinsic(GenTreeHWIntrinsic* node)
switch (intrinsicID)
{
- case NI_SSE_ConvertScalarToVector128Single:
- {
- assert(node->TypeGet() == TYP_SIMD16);
- assert(node->gtSIMDBaseType == TYP_FLOAT);
- assert(Compiler::ivalOfHWIntrinsic(intrinsicID) == -1);
-
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, node->gtSIMDBaseType);
- genHWIntrinsic_R_R_RM(node, ins);
- break;
- }
-
case NI_SSE_CompareEqualOrderedScalar:
case NI_SSE_CompareEqualUnorderedScalar:
{
@@ -985,19 +979,14 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node)
assert(op2 == nullptr);
assert(baseType == TYP_DOUBLE || baseType == TYP_FLOAT || baseType == TYP_INT || baseType == TYP_UINT ||
baseType == TYP_LONG || baseType == TYP_ULONG);
- if (op1Reg != targetReg)
+ instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ if (baseType == TYP_DOUBLE || baseType == TYP_FLOAT)
{
- instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
- if (baseType == TYP_DOUBLE || baseType == TYP_FLOAT)
- {
- emit->emitIns_R_R(ins, emitTypeSize(targetType), targetReg, op1Reg);
- }
- else
- {
- // TODO-XArch-Bug https://github.com/dotnet/coreclr/issues/16329
- // using hardcoded instruction as workaround for inexact type conversions
- emit->emitIns_R_R(INS_mov_xmm2i, emitActualTypeSize(baseType), op1Reg, targetReg);
- }
+ emit->emitIns_R_R(ins, emitTypeSize(targetType), targetReg, op1Reg);
+ }
+ else
+ {
+ emit->emitIns_R_R(ins, emitActualTypeSize(baseType), op1Reg, targetReg);
}
break;
}
@@ -1144,6 +1133,44 @@ void CodeGen::genSSE41Intrinsic(GenTreeHWIntrinsic* node)
break;
}
+ case NI_SSE41_Extract:
+ {
+ regNumber tmpTargetReg = REG_NA;
+ instruction ins = Compiler::insOfHWIntrinsic(intrinsicID, baseType);
+ if (baseType == TYP_FLOAT)
+ {
+ tmpTargetReg = node->ExtractTempReg();
+ }
+ auto emitSwCase = [&](unsigned i) {
+ if (baseType == TYP_FLOAT)
+ {
+ // extract instructions return to GP-registers, so it needs int size as the emitsize
+ emit->emitIns_SIMD_R_R_I(ins, emitTypeSize(TYP_INT), op1Reg, tmpTargetReg, (int)i);
+ emit->emitIns_R_R(INS_mov_i2xmm, EA_4BYTE, targetReg, tmpTargetReg);
+ }
+ else
+ {
+ emit->emitIns_SIMD_R_R_I(ins, emitTypeSize(TYP_INT), targetReg, op1Reg, (int)i);
+ }
+ };
+
+ if (op2->IsCnsIntOrI())
+ {
+ ssize_t ival = op2->AsIntCon()->IconValue();
+ emitSwCase((unsigned)ival);
+ }
+ else
+ {
+ // We emit a fallback case for the scenario when the imm-op is not a constant. This should
+ // normally happen when the intrinsic is called indirectly, such as via Reflection. However, it
+ // can also occur if the consumer calls it directly and just doesn't pass a constant value.
+ regNumber baseReg = node->ExtractTempReg();
+ regNumber offsReg = node->GetSingleTempReg();
+ genHWIntrinsicJumpTableFallback(intrinsicID, op2->gtRegNum, baseReg, offsReg, emitSwCase);
+ }
+ break;
+ }
+
default:
unreached();
break;
diff --git a/src/jit/hwintrinsiclistxarch.h b/src/jit/hwintrinsiclistxarch.h
index 69366edec3..5365c6e3d0 100644
--- a/src/jit/hwintrinsiclistxarch.h
+++ b/src/jit/hwintrinsiclistxarch.h
@@ -33,29 +33,29 @@ HARDWARE_INTRINSIC(SSE_AddScalar, "AddScalar"
HARDWARE_INTRINSIC(SSE_And, "And", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative)
HARDWARE_INTRINSIC(SSE_AndNot, "AndNot", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andnps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(SSE_CompareEqual, "CompareEqual", SSE, 0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative)
-HARDWARE_INTRINSIC(SSE_CompareEqualOrderedScalar, "CompareEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_CompareEqualOrderedScalar, "CompareEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE_CompareEqualScalar, "CompareEqualScalar", SSE, 0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE_CompareEqualUnorderedScalar, "CompareEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_CompareEqualUnorderedScalar, "CompareEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE_CompareGreaterThan, "CompareGreaterThan", SSE, 6, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
-HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrderedScalar, "CompareGreaterThanOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrderedScalar, "CompareGreaterThanOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE_CompareGreaterThanScalar, "CompareGreaterThanScalar", SSE, 6, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE_CompareGreaterThanUnorderedScalar, "CompareGreaterThanUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_CompareGreaterThanUnorderedScalar, "CompareGreaterThanUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqual, "CompareGreaterThanOrEqual", SSE, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
-HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqualOrderedScalar, "CompareGreaterThanOrEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqualOrderedScalar, "CompareGreaterThanOrEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqualScalar, "CompareGreaterThanOrEqualScalar", SSE, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqualUnorderedScalar, "CompareGreaterThanOrEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqualUnorderedScalar, "CompareGreaterThanOrEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE_CompareLessThan, "CompareLessThan", SSE, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
-HARDWARE_INTRINSIC(SSE_CompareLessThanOrderedScalar, "CompareLessThanOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_CompareLessThanOrderedScalar, "CompareLessThanOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE_CompareLessThanScalar, "CompareLessThanScalar", SSE, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE_CompareLessThanUnorderedScalar, "CompareLessThanUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_CompareLessThanUnorderedScalar, "CompareLessThanUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqual, "CompareLessThanOrEqual", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
-HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqualOrderedScalar, "CompareLessThanOrEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqualOrderedScalar, "CompareLessThanOrEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqualScalar, "CompareLessThanOrEqualScalar", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqualUnorderedScalar, "CompareLessThanOrEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqualUnorderedScalar, "CompareLessThanOrEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE_CompareNotEqual, "CompareNotEqual", SSE, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative)
-HARDWARE_INTRINSIC(SSE_CompareNotEqualOrderedScalar, "CompareNotEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_CompareNotEqualOrderedScalar, "CompareNotEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE_CompareNotEqualScalar, "CompareNotEqualScalar", SSE, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE_CompareNotEqualUnorderedScalar, "CompareNotEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_CompareNotEqualUnorderedScalar, "CompareNotEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE_CompareNotGreaterThan, "CompareNotGreaterThan", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(SSE_CompareNotGreaterThanScalar, "CompareNotGreaterThanScalar", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
HARDWARE_INTRINSIC(SSE_CompareNotGreaterThanOrEqual, "CompareNotGreaterThanOrEqual", SSE, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
@@ -68,12 +68,12 @@ HARDWARE_INTRINSIC(SSE_CompareOrdered, "CompareOrd
HARDWARE_INTRINSIC(SSE_CompareOrderedScalar, "CompareOrderedScalar", SSE, 7, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
HARDWARE_INTRINSIC(SSE_CompareUnordered, "CompareUnordered", SSE, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(SSE_CompareUnorderedScalar, "CompareUnorderedScalar", SSE, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE_ConvertToInt32, "ConvertToInt32", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE_ConvertToInt64, "ConvertToInt64", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE_ConvertToSingle, "ConvertToSingle", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_invalid}, HW_Category_Helper, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE_ConvertScalarToVector128Single, "ConvertScalarToVector128Single", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2ss, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE_ConvertToInt32WithTruncation, "ConvertToInt32WithTruncation", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE_ConvertToInt64WithTruncation, "ConvertToInt64WithTruncation", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_ConvertToInt32, "ConvertToInt32", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_ConvertToInt64, "ConvertToInt64", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_ConvertToSingle, "ConvertToSingle", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_ConvertScalarToVector128Single, "ConvertScalarToVector128Single", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2ss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_SecondArgMaybe64Bit|HW_Flag_BaseTypeFromFirstArg|HW_Flag_CopyUpperBits|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_ConvertToInt32WithTruncation, "ConvertToInt32WithTruncation", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_ConvertToInt64WithTruncation, "ConvertToInt64WithTruncation", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_64BitOnly|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE_Divide, "Divide", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(SSE_DivideScalar, "DivideScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
HARDWARE_INTRINSIC(SSE_LoadAlignedVector128, "LoadAlignedVector128", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movaps, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics)
@@ -134,29 +134,29 @@ HARDWARE_INTRINSIC(SSE2_And, "And",
HARDWARE_INTRINSIC(SSE2_AndNot, "AndNot", SSE2, -1, 16, 2, {INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_invalid, INS_andnpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(SSE2_Average, "Average", SSE2, -1, 16, 2, {INS_invalid, INS_pavgb, INS_invalid, INS_pavgw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative)
HARDWARE_INTRINSIC(SSE2_CompareEqual, "CompareEqual", SSE2, 0, 16, 2, {INS_pcmpeqb, INS_pcmpeqb, INS_pcmpeqw, INS_pcmpeqw, INS_pcmpeqd, INS_pcmpeqd, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative)
-HARDWARE_INTRINSIC(SSE2_CompareEqualOrderedScalar, "CompareEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_CompareEqualOrderedScalar, "CompareEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_CompareEqualScalar, "CompareEqualScalar", SSE2, 0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE2_CompareEqualUnorderedScalar, "CompareEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_CompareEqualUnorderedScalar, "CompareEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_CompareGreaterThan, "CompareGreaterThan", SSE2, 6, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
-HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrderedScalar, "CompareGreaterThanOrderedScalar", SSE2, -1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrderedScalar, "CompareGreaterThanOrderedScalar", SSE2, -1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_CompareGreaterThanScalar, "CompareGreaterThanScalar", SSE2, 6, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE2_CompareGreaterThanUnorderedScalar, "CompareGreaterThanUnorderedScalar", SSE2, -1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_CompareGreaterThanUnorderedScalar, "CompareGreaterThanUnorderedScalar", SSE2, -1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqual, "CompareGreaterThanOrEqual", SSE2, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
-HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqualOrderedScalar, "CompareGreaterThanOrEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqualOrderedScalar, "CompareGreaterThanOrEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqualScalar, "CompareGreaterThanOrEqualScalar", SSE2, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqualUnorderedScalar, "CompareGreaterThanOrEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqualUnorderedScalar, "CompareGreaterThanOrEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_CompareLessThan, "CompareLessThan", SSE2, 1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_Special, HW_Flag_NoFlag)
-HARDWARE_INTRINSIC(SSE2_CompareLessThanOrderedScalar, "CompareLessThanOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_CompareLessThanScalar, "CompareLessThanScalar", SSE2, 1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromArg|HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE2_CompareLessThanUnorderedScalar, "CompareLessThanUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_CompareLessThanOrderedScalar, "CompareLessThanOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_CompareLessThanScalar, "CompareLessThanScalar", SSE2, 1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
+HARDWARE_INTRINSIC(SSE2_CompareLessThanUnorderedScalar, "CompareLessThanUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqual, "CompareLessThanOrEqual", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
-HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqualOrderedScalar, "CompareLessThanOrEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqualOrderedScalar, "CompareLessThanOrEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqualScalar, "CompareLessThanOrEqualScalar", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqualUnorderedScalar, "CompareLessThanOrEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqualUnorderedScalar, "CompareLessThanOrEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_CompareNotEqual, "CompareNotEqual", SSE2, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative)
-HARDWARE_INTRINSIC(SSE2_CompareNotEqualOrderedScalar, "CompareNotEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_CompareNotEqualOrderedScalar, "CompareNotEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_CompareNotEqualScalar, "CompareNotEqualScalar", SSE2, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE2_CompareNotEqualUnorderedScalar, "CompareNotEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_CompareNotEqualUnorderedScalar, "CompareNotEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_CompareNotGreaterThan, "CompareNotGreaterThan", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(SSE2_CompareNotGreaterThanScalar, "CompareNotGreaterThanScalar", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
HARDWARE_INTRINSIC(SSE2_CompareNotGreaterThanOrEqual, "CompareNotGreaterThanOrEqual", SSE2, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
@@ -169,25 +169,27 @@ HARDWARE_INTRINSIC(SSE2_CompareOrdered, "CompareOrd
HARDWARE_INTRINSIC(SSE2_CompareOrderedScalar, "CompareOrderedScalar", SSE2, 7, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
HARDWARE_INTRINSIC(SSE2_CompareUnordered, "CompareUnordered", SSE2, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(SSE2_CompareUnorderedScalar, "CompareUnorderedScalar", SSE2, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE2_ConvertToDouble, "ConvertToDouble", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movsd}, HW_Category_Helper, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertToInt32, "ConvertToInt32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsd2si}, HW_Category_Special, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertToInt32WithTruncation, "ConvertToInt32WithTruncation", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertToInt64, "ConvertToInt64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_cvtsd2si}, HW_Category_Special, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertToInt64WithTruncation, "ConvertToInt64WithTruncation", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertToUInt32, "ConvertToUInt32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertToUInt64, "ConvertToUInt64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertToVector128Double, "ConvertToVector128Double", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2pd, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2pd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128Double, "ConvertScalarToVector128Double", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2sd, INS_invalid, INS_cvtsi2sd, INS_invalid, INS_cvtss2sd, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertToVector128Int32, "ConvertToVector128Int32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_cvtpd2dq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertToDouble, "ConvertToDouble", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movsd}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertToInt32, "ConvertToInt32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertToInt32WithTruncation, "ConvertToInt32WithTruncation", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertToInt64, "ConvertToInt64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_cvtsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertToInt64WithTruncation, "ConvertToInt64WithTruncation", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_64BitOnly|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertToUInt32, "ConvertToUInt32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertToUInt64, "ConvertToUInt64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertToVector128Double, "ConvertToVector128Double", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2pd, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2pd, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128Double, "ConvertScalarToVector128Double", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2sd, INS_invalid, INS_cvtsi2sd, INS_invalid, INS_cvtss2sd, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_SecondArgMaybe64Bit|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertToVector128Int32, "ConvertToVector128Int32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_cvtpd2dq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128Int32, "ConvertScalarToVector128Int32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertToVector128Int32WithTruncation, "ConvertToVector128Int32WithTruncation", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttps2dq, INS_cvttpd2dq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128Int64, "ConvertScalarToVector128Int64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertToVector128Single, "ConvertToVector128Single", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2ps}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128Single, "ConvertScalarToVector128Single", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsd2ss}, HW_Category_Special, HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertToVector128Int32WithTruncation, "ConvertToVector128Int32WithTruncation", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttps2dq, INS_cvttpd2dq}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128Int64, "ConvertScalarToVector128Int64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_64BitOnly|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertToVector128Single, "ConvertToVector128Single", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtdq2ps, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2ps}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128Single, "ConvertScalarToVector128Single", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsd2ss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128UInt32, "ConvertScalarToVector128UInt32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128UInt64, "ConvertScalarToVector128UInt64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_ConvertScalarToVector128UInt64, "ConvertScalarToVector128UInt64", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_i2xmm, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_64BitOnly|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_Divide, "Divide", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(SSE2_DivideScalar, "DivideScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_divsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
+HARDWARE_INTRINSIC(SSE2_Extract, "Extract", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_pextrw, INS_pextrw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_Insert, "Insert", SSE2, -1, 16, 3, {INS_invalid, INS_invalid, INS_pinsrw, INS_pinsrw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM)
HARDWARE_INTRINSIC(SSE2_LoadAlignedVector128, "LoadAlignedVector128", SSE2, -1, 16, 1, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_invalid, INS_movapd}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_LoadFence, "LoadFence", SSE2, -1, 0, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_LoadScalarVector128, "LoadScalarVector128", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_movd, INS_movq, INS_movq, INS_invalid, INS_movsdsse2}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics)
@@ -200,16 +202,16 @@ HARDWARE_INTRINSIC(SSE2_Min, "Min",
HARDWARE_INTRINSIC(SSE2_MinScalar, "MinScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_minsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
HARDWARE_INTRINSIC(SSE2_MoveMask, "MoveMask", SSE2, -1, 16, 1, {INS_pmovmskb, INS_pmovmskb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movmskpd}, HW_Category_Special, HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE2_MoveScalar, "MoveScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movsdsse2}, HW_Category_SIMDScalar, HW_Flag_NoContainment)
-HARDWARE_INTRINSIC(SSE2_Multiply, "Multiply", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmuludq, INS_invalid, INS_invalid, INS_invalid, INS_mulpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromArg)
+HARDWARE_INTRINSIC(SSE2_Multiply, "Multiply", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmuludq, INS_invalid, INS_invalid, INS_invalid, INS_mulpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(SSE2_MultiplyHigh, "MultiplyHigh", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_pmulhw, INS_pmulhuw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative)
-HARDWARE_INTRINSIC(SSE2_MultiplyHorizontalAdd, "MultiplyHorizontalAdd", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_pmaddwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromArg)
+HARDWARE_INTRINSIC(SSE2_MultiplyHorizontalAdd, "MultiplyHorizontalAdd", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_pmaddwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(SSE2_MultiplyLow, "MultiplyLow", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_pmullw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative)
HARDWARE_INTRINSIC(SSE2_MultiplyScalar, "MultiplyScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mulsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
HARDWARE_INTRINSIC(SSE2_Or, "Or", SSE2, -1, 16, 2, {INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_por, INS_invalid, INS_orpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative)
-HARDWARE_INTRINSIC(SSE2_PackSignedSaturate, "PackSignedSaturate", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_packsswb, INS_invalid, INS_packssdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromArg)
-HARDWARE_INTRINSIC(SSE2_PackUnsignedSaturate, "PackUnsignedSaturate", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_packuswb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromArg)
+HARDWARE_INTRINSIC(SSE2_PackSignedSaturate, "PackSignedSaturate", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_packsswb, INS_invalid, INS_packssdw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg)
+HARDWARE_INTRINSIC(SSE2_PackUnsignedSaturate, "PackUnsignedSaturate", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_packuswb, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(SSE2_SetZeroVector128, "SetZeroVector128", SSE2, -1, 16, 0, {INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_pxor, INS_invalid, INS_xorpd}, HW_Category_Helper, HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_SumAbsoluteDifferences, "SumAbsoluteDifferences", SSE2, -1, 16, 2, {INS_invalid, INS_psadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromArg)
+HARDWARE_INTRINSIC(SSE2_SumAbsoluteDifferences, "SumAbsoluteDifferences", SSE2, -1, 16, 2, {INS_invalid, INS_psadbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(SSE2_ShiftLeftLogical, "ShiftLeftLogical", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_psllw, INS_psllw, INS_pslld, INS_pslld, INS_psllq, INS_psllq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM)
HARDWARE_INTRINSIC(SSE2_ShiftLeftLogical128BitLane, "ShiftLeftLogical128BitLane", SSE2, -1, 16, 2, {INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_pslldq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM)
HARDWARE_INTRINSIC(SSE2_ShiftRightArithmetic, "ShiftRightArithmetic", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_psraw, INS_invalid, INS_psrad, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_MaybeIMM|HW_Flag_NoJmpTableIMM|HW_Flag_FullRangeIMM)
@@ -273,12 +275,14 @@ HARDWARE_INTRINSIC(SSE41_BlendVariable, "BlendVaria
HARDWARE_INTRINSIC(SSE41_Ceiling, "Ceiling", SSE41, 10, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE41_CeilingScalar, "CeilingScalar", SSE41, 10, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_Special, HW_Flag_CopyUpperBits)
HARDWARE_INTRINSIC(SSE41_CompareEqual, "CompareEqual", SSE41, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pcmpeqq, INS_pcmpeqq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative)
-HARDWARE_INTRINSIC(SSE41_ConvertToVector128Int16, "ConvertToVector128Int16", SSE41, -1, 16, 1, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE41_ConvertToVector128Int32, "ConvertToVector128Int32", SSE41, -1, 16, 1, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE41_ConvertToVector128Int64, "ConvertToVector128Int64", SSE41, -1, 16, 1, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE41_ConvertToVector128Int16, "ConvertToVector128Int16", SSE41, -1, 16, 1, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE41_ConvertToVector128Int32, "ConvertToVector128Int32", SSE41, -1, 16, 1, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE41_ConvertToVector128Int64, "ConvertToVector128Int64", SSE41, -1, 16, 1, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE41_DotProduct, "DotProduct", SSE41, -1, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_dpps, INS_dppd}, HW_Category_IMM, HW_Flag_FullRangeIMM)
+HARDWARE_INTRINSIC(SSE41_Extract, "Extract", SSE41, -1, 16, 2, {INS_pextrb, INS_pextrb, INS_invalid, INS_invalid, INS_pextrd, INS_pextrd, INS_pextrq, INS_pextrq, INS_extractps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiIns|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE41_Floor, "Floor", SSE41, 9, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE41_FloorScalar, "FloorScalar", SSE41, 9, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_Special, HW_Flag_CopyUpperBits)
+HARDWARE_INTRINSIC(SSE41_Insert, "Insert", SSE41, -1, 16, 3, {INS_pinsrb, INS_pinsrb, INS_invalid, INS_invalid, INS_pinsrd, INS_pinsrd, INS_pinsrq, INS_pinsrq, INS_insertps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_SecondArgMaybe64Bit)
HARDWARE_INTRINSIC(SSE41_LoadAlignedVector128NonTemporal, "LoadAlignedVector128NonTemporal", SSE41, -1, 16, 1, {INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_movntdqa, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE41_Max, "Max", SSE41, -1, 16, 2, {INS_pmaxsb, INS_invalid, INS_invalid, INS_pmaxuw, INS_pmaxsd, INS_pmaxud, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(SSE41_Min, "Min", SSE41, -1, 16, 2, {INS_pminsb, INS_invalid, INS_invalid, INS_pminuw, INS_pminsd, INS_pminud, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
@@ -297,12 +301,12 @@ HARDWARE_INTRINSIC(SSE41_RoundToPositiveInfinity, "RoundToPos
HARDWARE_INTRINSIC(SSE41_RoundToPositiveInfinityScalar, "RoundToPositiveInfinityScalar", SSE41, 10, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_Special, HW_Flag_CopyUpperBits)
HARDWARE_INTRINSIC(SSE41_RoundToZero, "RoundToZero", SSE41, 11, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE41_RoundToZeroScalar, "RoundToZeroScalar", SSE41, 11, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_Special, HW_Flag_CopyUpperBits)
-HARDWARE_INTRINSIC(SSE41_TestAllOnes, "TestAllOnes", SSE41, -1, 16, 1, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE41_TestAllZeros, "TestAllZeros", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment)
-HARDWARE_INTRINSIC(SSE41_TestC, "TestC", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment)
-HARDWARE_INTRINSIC(SSE41_TestMixOnesZeros, "TestMixOnesZeros", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment)
-HARDWARE_INTRINSIC(SSE41_TestNotZAndNotC, "TestNotZAndNotC", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment)
-HARDWARE_INTRINSIC(SSE41_TestZ, "TestZ", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment)
+HARDWARE_INTRINSIC(SSE41_TestAllOnes, "TestAllOnes", SSE41, -1, 16, 1, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics|HW_Flag_BaseTypeFromFirstArg)
+HARDWARE_INTRINSIC(SSE41_TestAllZeros, "TestAllZeros", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg)
+HARDWARE_INTRINSIC(SSE41_TestC, "TestC", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg)
+HARDWARE_INTRINSIC(SSE41_TestMixOnesZeros, "TestMixOnesZeros", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg)
+HARDWARE_INTRINSIC(SSE41_TestNotZAndNotC, "TestNotZAndNotC", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg)
+HARDWARE_INTRINSIC(SSE41_TestZ, "TestZ", SSE41, -1, 16, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg)
// SSE42 Intrinsics
HARDWARE_INTRINSIC(SSE42_IsSupported, "get_IsSupported", SSE42, -1, 0, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IsSupportedProperty, HW_Flag_NoFlag)
@@ -352,9 +356,9 @@ HARDWARE_INTRINSIC(AVX_Store, "Store",
HARDWARE_INTRINSIC(AVX_StoreAligned, "StoreAligned", AVX, -1, 32, 2, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movaps, INS_movapd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(AVX_StoreAlignedNonTemporal, "StoreAlignedNonTemporal", AVX, -1, 32, 2, {INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntdq, INS_movntps, INS_movntpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(AVX_Subtract, "Subtract", AVX, -1, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subps, INS_subpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
-HARDWARE_INTRINSIC(AVX_TestC, "TestC", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_OneTypeGeneric|HW_Flag_UnfixedSIMDSize|HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromArg)
-HARDWARE_INTRINSIC(AVX_TestNotZAndNotC, "TestNotZAndNotC", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_OneTypeGeneric|HW_Flag_UnfixedSIMDSize|HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromArg)
-HARDWARE_INTRINSIC(AVX_TestZ, "TestZ", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_OneTypeGeneric|HW_Flag_UnfixedSIMDSize|HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromArg)
+HARDWARE_INTRINSIC(AVX_TestC, "TestC", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_OneTypeGeneric|HW_Flag_UnfixedSIMDSize|HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg)
+HARDWARE_INTRINSIC(AVX_TestNotZAndNotC, "TestNotZAndNotC", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_OneTypeGeneric|HW_Flag_UnfixedSIMDSize|HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg)
+HARDWARE_INTRINSIC(AVX_TestZ, "TestZ", AVX, -1, 0, 2, {INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_ptest, INS_vtestps, INS_vtestpd}, HW_Category_SimpleSIMD, HW_Flag_OneTypeGeneric|HW_Flag_UnfixedSIMDSize|HW_Flag_MultiIns|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(AVX_UnpackHigh, "UnpackHigh", AVX, -1, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_unpckhps, INS_unpckhpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(AVX_UnpackLow, "UnpackLow", AVX, -1, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_unpcklps, INS_unpcklpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(AVX_Xor, "Xor", AVX, -1, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_xorps, INS_xorpd}, HW_Category_SimpleSIMD, HW_Flag_Commutative)
diff --git a/src/jit/hwintrinsicxarch.cpp b/src/jit/hwintrinsicxarch.cpp
index 36f48ba732..86a9489be0 100644
--- a/src/jit/hwintrinsicxarch.cpp
+++ b/src/jit/hwintrinsicxarch.cpp
@@ -200,12 +200,22 @@ unsigned Compiler::simdSizeOfHWIntrinsic(NamedIntrinsic intrinsic, CORINFO_SIG_I
return hwIntrinsicInfoArray[intrinsic - NI_HW_INTRINSIC_START - 1].simdSize;
}
- CORINFO_CLASS_HANDLE typeHnd =
- ((flags & HW_Flag_BaseTypeFromArg) == 0) ? sig->retTypeSigClass : info.compCompHnd->getArgClass(sig, sig->args);
+ CORINFO_CLASS_HANDLE typeHnd = nullptr;
- int simdSize = getSIMDTypeSizeInBytes(typeHnd);
- assert(simdSize > 0);
- return (unsigned)simdSize;
+ if (JITtype2varType(sig->retType) == TYP_STRUCT)
+ {
+ typeHnd = sig->retTypeSigClass;
+ }
+ else
+ {
+ assert((flags & HW_Flag_BaseTypeFromFirstArg) != 0);
+ typeHnd = info.compCompHnd->getArgClass(sig, sig->args);
+ }
+
+ unsigned simdSize = 0;
+ var_types baseType = getBaseTypeAndSizeOfSIMDType(typeHnd, &simdSize);
+ assert(simdSize > 0 && baseType != TYP_UNKNOWN);
+ return simdSize;
}
//------------------------------------------------------------------------
@@ -486,7 +496,6 @@ bool Compiler::isFullyImplmentedISAClass(InstructionSet isa)
switch (isa)
{
case InstructionSet_SSE2:
- case InstructionSet_SSE41:
case InstructionSet_SSE42:
case InstructionSet_AVX:
case InstructionSet_AVX2:
@@ -500,6 +509,7 @@ bool Compiler::isFullyImplmentedISAClass(InstructionSet isa)
case InstructionSet_SSE:
case InstructionSet_SSE3:
case InstructionSet_SSSE3:
+ case InstructionSet_SSE41:
case InstructionSet_LZCNT:
case InstructionSet_POPCNT:
return true;
@@ -551,10 +561,37 @@ bool Compiler::compSupportsHWIntrinsic(InstructionSet isa)
isFullyImplmentedISAClass(isa));
}
-static bool isTypeSupportedForIntrinsic(var_types type)
+//------------------------------------------------------------------------
+// hwIntrinsicSignatureTypeSupported: platform support of hardware intrinsics
+//
+// Arguments:
+// retType - return type
+// sig - intrinsic signature
+// flags - flags of the intrinsics
+//
+// Return Value:
+// Returns true iff the given type signature is supported
+// Notes:
+// - This is only used on 32-bit systems to determine whether the signature uses no 64-bit registers.
+// - The `retType` is passed to avoid another call to the type system, as it has already been retrieved.
+bool Compiler::hwIntrinsicSignatureTypeSupported(var_types retType, CORINFO_SIG_INFO* sig, HWIntrinsicFlag flags)
{
#ifdef _TARGET_X86_
- return !varTypeIsLong(type);
+ CORINFO_CLASS_HANDLE argClass;
+
+ if ((flags & HW_Flag_64BitOnly) != 0)
+ {
+ return false;
+ }
+ else if ((flags & HW_Flag_SecondArgMaybe64Bit) != 0)
+ {
+ assert(sig->numArgs >= 2);
+ CorInfoType corType =
+ strip(info.compCompHnd->getArgType(sig, info.compCompHnd->getArgNext(sig->args), &argClass));
+ return !varTypeIsLong(JITtype2varType(corType));
+ }
+
+ return !varTypeIsLong(retType);
#else
return true;
#endif
@@ -609,9 +646,10 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
// This intrinsic is supported if
// - the ISA is available on the underlying hardware (compSupports returns true)
// - the compiler supports this hardware intrinsics (compSupportsHWIntrinsic returns true)
- // - intrinsics do not require 64-bit registers (r64) on 32-bit platforms (isTypeSupportedForIntrinsic returns
+ // - intrinsics do not require 64-bit registers (r64) on 32-bit platforms (signatureTypeSupproted returns
// true)
- bool issupported = compSupports(isa) && compSupportsHWIntrinsic(isa) && isTypeSupportedForIntrinsic(retType);
+ bool issupported =
+ compSupports(isa) && compSupportsHWIntrinsic(isa) && hwIntrinsicSignatureTypeSupported(retType, sig, flags);
if (category == HW_Category_IsSupportedProperty)
{
@@ -656,17 +694,25 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
bool isTableDriven = impIsTableDrivenHWIntrinsic(category, flags);
- if (isTableDriven && (!varTypeIsSIMD(retType) || ((flags & HW_Flag_BaseTypeFromArg) != 0)))
+ if (isTableDriven && ((category == HW_Category_MemoryStore) ||
+ ((flags & (HW_Flag_BaseTypeFromFirstArg | HW_Flag_BaseTypeFromSecondArg)) != 0)))
{
- if (retType != TYP_VOID)
+ if ((flags & HW_Flag_BaseTypeFromFirstArg) != 0)
{
baseType = getBaseTypeOfSIMDType(info.compCompHnd->getArgClass(sig, sig->args));
}
else
{
- assert(category == HW_Category_MemoryStore);
- baseType =
- getBaseTypeOfSIMDType(info.compCompHnd->getArgClass(sig, info.compCompHnd->getArgNext(sig->args)));
+ assert((category == HW_Category_MemoryStore) || ((flags & HW_Flag_BaseTypeFromSecondArg) != 0));
+ CORINFO_ARG_LIST_HANDLE secondArg = info.compCompHnd->getArgNext(sig->args);
+ CORINFO_CLASS_HANDLE secondArgClass = info.compCompHnd->getArgClass(sig, secondArg);
+ baseType = getBaseTypeOfSIMDType(secondArgClass);
+
+ if (baseType == TYP_UNKNOWN) // the second argument is not a vector
+ {
+ baseType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, secondArg, &secondArgClass)));
+ assert(baseType != TYP_STRUCT);
+ }
}
assert(baseType != TYP_UNKNOWN);
@@ -769,10 +815,6 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
return impSSEIntrinsic(intrinsic, method, sig, mustExpand);
case InstructionSet_SSE2:
return impSSE2Intrinsic(intrinsic, method, sig, mustExpand);
- case InstructionSet_SSE3:
- return impSSE3Intrinsic(intrinsic, method, sig, mustExpand);
- case InstructionSet_SSSE3:
- return impSSSE3Intrinsic(intrinsic, method, sig, mustExpand);
case InstructionSet_SSE41:
return impSSE41Intrinsic(intrinsic, method, sig, mustExpand);
case InstructionSet_SSE42:
@@ -837,30 +879,6 @@ GenTree* Compiler::impSSEIntrinsic(NamedIntrinsic intrinsic,
break;
}
- case NI_SSE_ConvertScalarToVector128Single:
- {
- assert(sig->numArgs == 2);
- assert(getBaseTypeOfSIMDType(sig->retTypeSigClass) == TYP_FLOAT);
-
-#ifdef _TARGET_X86_
- CORINFO_CLASS_HANDLE argClass;
-
- CORINFO_ARG_LIST_HANDLE argLst = info.compCompHnd->getArgNext(sig->args);
- CorInfoType corType =
- strip(info.compCompHnd->getArgType(sig, argLst, &argClass)); // type of the second argument
-
- if (varTypeIsLong(JITtype2varType(corType)))
- {
- return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, method, sig, mustExpand);
- }
-#endif // _TARGET_X86_
-
- op2 = impPopStack().val;
- op1 = impSIMDPopStack(TYP_SIMD16);
- retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, op2, intrinsic, TYP_FLOAT, simdSize);
- break;
- }
-
case NI_SSE_ReciprocalScalar:
case NI_SSE_ReciprocalSqrtScalar:
case NI_SSE_SqrtScalar:
@@ -959,88 +977,6 @@ GenTree* Compiler::impSSE2Intrinsic(NamedIntrinsic intrinsic,
break;
}
- case NI_SSE2_ConvertScalarToVector128Double:
- {
- assert(sig->numArgs == 2);
- assert(getBaseTypeOfSIMDType(sig->retTypeSigClass) == TYP_DOUBLE);
-
- argList = info.compCompHnd->getArgNext(sig->args);
- CorInfoType corType =
- strip(info.compCompHnd->getArgType(sig, argList, &argClass)); // type of the second argument
-
- baseType = JITtype2varType(corType);
-
-#ifdef _TARGET_X86_
- if (varTypeIsLong(JITtype2varType(corType)))
- {
- return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, method, sig, mustExpand);
- }
-#endif // _TARGET_X86_
-
- if (baseType == TYP_STRUCT)
- {
- baseType = TYP_FLOAT; // it is the only type passed as Vector
- op2 = impSIMDPopStack(TYP_SIMD16);
- }
- else
- {
- op2 = impPopStack().val;
- }
-
- op1 = impSIMDPopStack(TYP_SIMD16);
- retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, op2, intrinsic, baseType, simdSize);
-
- break;
- }
-
- case NI_SSE2_ConvertScalarToVector128Int64:
- case NI_SSE2_ConvertScalarToVector128UInt64:
- {
- assert(sig->numArgs == 1);
- baseType = getBaseTypeOfSIMDType(sig->retTypeSigClass);
- assert(baseType == TYP_LONG || baseType == TYP_ULONG);
-
-#ifdef _TARGET_X86_
- return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, method, sig, mustExpand);
-#endif // _TARGET_X86_
-
- op1 = impPopStack().val;
- retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, intrinsic, baseType, simdSize);
- break;
- }
-
- case NI_SSE2_ConvertScalarToVector128Single:
- {
- assert(sig->numArgs == 2);
- assert(getBaseTypeOfSIMDType(sig->retTypeSigClass) == TYP_FLOAT);
-
- op2 = impSIMDPopStack(TYP_SIMD16);
- op1 = impSIMDPopStack(TYP_SIMD16);
- retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, op2, intrinsic, TYP_DOUBLE, simdSize);
- break;
- }
-
- case NI_SSE2_ConvertToInt32:
- case NI_SSE2_ConvertToInt64:
- {
- assert(sig->numArgs == 1);
- op1 = impSIMDPopStack(TYP_SIMD16);
- retType = JITtype2varType(sig->retType);
- baseType = getBaseTypeOfSIMDType(info.compCompHnd->getArgClass(sig, sig->args));
- retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, baseType, simdSize);
- break;
- }
-
- case NI_SSE2_ConvertToUInt32:
- case NI_SSE2_ConvertToUInt64:
- {
- assert(sig->numArgs == 1);
- op1 = impSIMDPopStack(TYP_SIMD16);
- baseType = JITtype2varType(sig->retType);
- retNode = gtNewSimdHWIntrinsicNode(baseType, op1, intrinsic, baseType, simdSize);
- break;
- }
-
case NI_SSE2_LoadFence:
case NI_SSE2_MemoryFence:
{
@@ -1070,22 +1006,6 @@ GenTree* Compiler::impSSE2Intrinsic(NamedIntrinsic intrinsic,
return retNode;
}
-GenTree* Compiler::impSSE3Intrinsic(NamedIntrinsic intrinsic,
- CORINFO_METHOD_HANDLE method,
- CORINFO_SIG_INFO* sig,
- bool mustExpand)
-{
- return nullptr;
-}
-
-GenTree* Compiler::impSSSE3Intrinsic(NamedIntrinsic intrinsic,
- CORINFO_METHOD_HANDLE method,
- CORINFO_SIG_INFO* sig,
- bool mustExpand)
-{
- return nullptr;
-}
-
GenTree* Compiler::impSSE41Intrinsic(NamedIntrinsic intrinsic,
CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig,
diff --git a/src/jit/instrsxarch.h b/src/jit/instrsxarch.h
index ddd03ddb74..d448afc977 100644
--- a/src/jit/instrsxarch.h
+++ b/src/jit/instrsxarch.h
@@ -452,6 +452,13 @@ INST3( movsldup, "movsldup" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SS
INST3( movshdup, "movshdup" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSEFLT(0x16)) // Replicate odd-indexed Single FP Values
INST3( phminposuw, "phminposuw" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x41)) // Packed Horizontal Word Minimum
INST3( mpsadbw, "mpsadbw" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE3A(0x42)) // Compute Multiple Packed Sums of Absolute Difference
+INST3( pinsrb, "pinsrb" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE3A(0x20)) // Insert Byte
+INST3( pinsrd, "pinsrd" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE3A(0x22)) // Insert Dword
+INST3( pinsrq, "pinsrq" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE3A(0x22)) // Insert Qword
+INST3( pextrb, "pextrb" , 0, IUM_WR, 0, 0, SSE3A(0x14), BAD_CODE, BAD_CODE) // Extract Byte
+INST3( pextrd, "pextrd" , 0, IUM_WR, 0, 0, SSE3A(0x16), BAD_CODE, BAD_CODE) // Extract Dword
+INST3( pextrq, "pextrq" , 0, IUM_WR, 0, 0, SSE3A(0x16), BAD_CODE, BAD_CODE) // Extract Qword
+INST3( extractps, "extractps" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE3A(0x17)) // Extract Packed Floating-Point Values
INST3(LAST_SSE4_INSTRUCTION, "LAST_SSE4_INSTRUCTION", 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, BAD_CODE)
diff --git a/src/jit/lsraxarch.cpp b/src/jit/lsraxarch.cpp
index d56abed3cc..fdb875a827 100644
--- a/src/jit/lsraxarch.cpp
+++ b/src/jit/lsraxarch.cpp
@@ -2255,6 +2255,7 @@ void LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree)
{
TreeNodeInfo* info = currentNodeInfo;
NamedIntrinsic intrinsicID = intrinsicTree->gtHWIntrinsicId;
+ var_types baseType = intrinsicTree->gtSIMDBaseType;
InstructionSet isa = Compiler::isaOfHWIntrinsic(intrinsicID);
HWIntrinsicCategory category = Compiler::categoryOfHWIntrinsic(intrinsicID);
HWIntrinsicFlag flags = Compiler::flagsOfHWIntrinsic(intrinsicID);
@@ -2390,6 +2391,19 @@ void LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree)
break;
}
+ case NI_SSE41_Extract:
+ if (baseType == TYP_FLOAT)
+ {
+ info->internalIntCount += 1;
+ }
+#ifdef _TARGET_X86_
+ else if (varTypeIsByte(baseType))
+ {
+ info->setDstCandidates(this, RBM_BYTE_REGS);
+ }
+#endif
+ break;
+
#ifdef _TARGET_X86_
case NI_SSE42_Crc32:
{
diff --git a/src/jit/namedintrinsiclist.h b/src/jit/namedintrinsiclist.h
index 7ad997ead7..91c9720580 100644
--- a/src/jit/namedintrinsiclist.h
+++ b/src/jit/namedintrinsiclist.h
@@ -75,8 +75,8 @@ enum HWIntrinsicFlag : unsigned int
// some SIMD scalar intrinsics need the semantics of copying upper bits from the source operand
HW_Flag_CopyUpperBits = 0x200,
- // Select base type using argument type
- HW_Flag_BaseTypeFromArg = 0x400,
+ // Select base type using the first argument type
+ HW_Flag_BaseTypeFromFirstArg = 0x400,
// Indicates compFloatingPointUsed does not need to be set.
HW_Flag_NoFloatingPointUsed = 0x800,
@@ -89,9 +89,22 @@ enum HWIntrinsicFlag : unsigned int
// the imm intrinsic does not need jumptable fallback when it gets non-const argument
HW_Flag_NoJmpTableIMM = 0x2000,
+ // 64-bit intrinsics
+ // Intrinsics that operate over 64-bit general purpose registers are not supported on 32-bit platform
+ HW_Flag_64BitOnly = 0x4000,
+ HW_Flag_SecondArgMaybe64Bit = 0x8000,
+
+ // Select base type using the second argument type
+ HW_Flag_BaseTypeFromSecondArg = 0x10000,
+
+ // Specail codegen
+ // the intrinsics need special rules in CodeGen,
+ // but can be table-driven in the front-end
+ HW_Flag_SpecialCodeGen = 0x20000,
+
// No Read/Modify/Write Semantics
- // the intrinsic does not have read/modify/write semantics and doesn't need
- HW_Flag_NoRMWSemantics = 0x4000,
+ // the intrinsic doesn't have read/modify/write semantics in two/three-operand form.
+ HW_Flag_NoRMWSemantics = 0x40000,
};
inline HWIntrinsicFlag operator|(HWIntrinsicFlag c1, HWIntrinsicFlag c2)
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/ExtractScalarTest.template b/tests/src/JIT/HardwareIntrinsics/X86/Shared/ExtractScalarTest.template
new file mode 100644
index 0000000000..fae1d35fb1
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/ExtractScalarTest.template
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 {2}{4}{7}()
+ {{
+ var test = new SimpleUnaryOpTest__{2}{4}{7}();
+
+ try
+ {{
+ if (test.IsSupported)
+ {{
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if ({1}.IsSupported)
+ {{
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }}
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if ({1}.IsSupported)
+ {{
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }}
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if ({1}.IsSupported)
+ {{
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }}
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }}
+ else
+ {{
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }}
+ }}
+ catch (PlatformNotSupportedException)
+ {{
+ test.Succeeded = true;
+ }}
+
+ if (!test.Succeeded)
+ {{
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }}
+ }}
+ }}
+
+ public sealed unsafe class SimpleUnaryOpTest__{2}{4}{7}
+ {{
+ private const int VectorSize = {8};
+
+ private const int Op1ElementCount = VectorSize / sizeof({6});
+ private const int RetElementCount = VectorSize / sizeof({4});
+
+ private static {6}[] _data = new {6}[Op1ElementCount];
+
+ private static {5}<{6}> _clsVar;
+
+ private {5}<{6}> _fld;
+
+ private SimpleUnaryOpTest__DataTable<{4}, {6}> _dataTable;
+
+ static SimpleUnaryOpTest__{2}{4}{7}()
+ {{
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) {{ _data[i] = {9}; }}
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{5}<{6}>, byte>(ref _clsVar), ref Unsafe.As<{6}, byte>(ref _data[0]), VectorSize);
+ }}
+
+ public SimpleUnaryOpTest__{2}{4}{7}()
+ {{
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) {{ _data[i] = {9}; }}
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{5}<{6}>, byte>(ref _fld), ref Unsafe.As<{6}, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) {{ _data[i] = {9}; }}
+ _dataTable = new SimpleUnaryOpTest__DataTable<{4}, {6}>(_data, new {4}[RetElementCount], VectorSize);
+ }}
+
+ public bool IsSupported => {0}.IsSupported;
+
+ public bool Succeeded {{ get; set; }}
+
+ public void RunBasicScenario_UnsafeRead()
+ {{
+ var result = {0}.{2}(
+ Unsafe.Read<{5}<{6}>>(_dataTable.inArrayPtr),
+ {7}
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }}
+
+ public void RunBasicScenario_Load()
+ {{
+ var result = {0}.{2}(
+ {1}.Load{5}(({6}*)(_dataTable.inArrayPtr)),
+ {7}
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }}
+
+ public void RunBasicScenario_LoadAligned()
+ {{
+ var result = {0}.{2}(
+ {1}.LoadAligned{5}(({6}*)(_dataTable.inArrayPtr)),
+ {7}
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }}
+
+ public void RunReflectionScenario_UnsafeRead()
+ {{
+ var result = typeof({0}).GetMethod(nameof({0}.{2}), new Type[] {{ typeof({5}<{6}>), typeof(byte) }})
+ .Invoke(null, new object[] {{
+ Unsafe.Read<{5}<{6}>>(_dataTable.inArrayPtr),
+ (byte){7}
+ }});
+
+ Unsafe.Write(_dataTable.outArrayPtr, ({4})(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }}
+
+ public void RunReflectionScenario_Load()
+ {{
+ var result = typeof({0}).GetMethod(nameof({0}.{2}), new Type[] {{ typeof({5}<{6}>), typeof(byte) }})
+ .Invoke(null, new object[] {{
+ {1}.Load{5}(({6}*)(_dataTable.inArrayPtr)),
+ (byte){7}
+ }});
+
+ Unsafe.Write(_dataTable.outArrayPtr, ({4})(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }}
+
+ public void RunReflectionScenario_LoadAligned()
+ {{
+ var result = typeof({0}).GetMethod(nameof({0}.{2}), new Type[] {{ typeof({5}<{6}>), typeof(byte) }})
+ .Invoke(null, new object[] {{
+ {1}.LoadAligned{5}(({6}*)(_dataTable.inArrayPtr)),
+ (byte){7}
+ }});
+
+ Unsafe.Write(_dataTable.outArrayPtr, ({4})(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }}
+
+ public void RunClsVarScenario()
+ {{
+ var result = {0}.{2}(
+ _clsVar,
+ {7}
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }}
+
+ public void RunLclVarScenario_UnsafeRead()
+ {{
+ var firstOp = Unsafe.Read<{5}<{6}>>(_dataTable.inArrayPtr);
+ var result = {0}.{2}(firstOp, {7});
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }}
+
+ public void RunLclVarScenario_Load()
+ {{
+ var firstOp = {1}.Load{5}(({6}*)(_dataTable.inArrayPtr));
+ var result = {0}.{2}(firstOp, {7});
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }}
+
+ public void RunLclVarScenario_LoadAligned()
+ {{
+ var firstOp = {1}.LoadAligned{5}(({6}*)(_dataTable.inArrayPtr));
+ var result = {0}.{2}(firstOp, {7});
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }}
+
+ public void RunLclFldScenario()
+ {{
+ var test = new SimpleUnaryOpTest__{2}{4}{7}();
+ var result = {0}.{2}(test._fld, {7});
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }}
+
+ public void RunFldScenario()
+ {{
+ var result = {0}.{2}(_fld, {7});
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }}
+
+ public void RunUnsupportedScenario()
+ {{
+ Succeeded = false;
+
+ try
+ {{
+ RunBasicScenario_UnsafeRead();
+ }}
+ catch (PlatformNotSupportedException)
+ {{
+ Succeeded = true;
+ }}
+ }}
+
+ private void ValidateResult({5}<{6}> firstOp, void* result, [CallerMemberName] string method = "")
+ {{
+ {6}[] inArray = new {6}[Op1ElementCount];
+ {4}[] outArray = new {4}[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{4}, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }}
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {{
+ {6}[] inArray = new {6}[Op1ElementCount];
+ {4}[] outArray = new {4}[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{6}, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{4}, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }}
+
+ private void ValidateResult({6}[] firstOp, {4}[] result, [CallerMemberName] string method = "")
+ {{
+ if ({10})
+ {{
+ Succeeded = false;
+ }}
+
+ if (!Succeeded)
+ {{
+ Console.WriteLine($"{{nameof({0})}}.{{nameof({0}.{2})}}<{4}>({5}<{6}><9>): {{method}} failed:");
+ Console.WriteLine($" firstOp: ({{string.Join(", ", firstOp)}})");
+ Console.WriteLine($" result: ({{string.Join(", ", result)}})");
+ Console.WriteLine();
+ }}
+ }}
+ }}
+}}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx
index 6192d9e879..cdd9ba23bd 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx
@@ -211,6 +211,14 @@ private static readonly (string templateFileName, string[] templateData)[] Sse2I
("ImmUnOpTest.template", new string[] { "Sse2", "Sse2", "ShiftRightLogical128BitLane", "Vector128", "UInt32", "Vector128", "UInt32", "1", "16", "(uint)8", "result[0] != 134217728", "(i == 3 ? result[i] != 0 : result[i] != 134217728)"}),
("ImmUnOpTest.template", new string[] { "Sse2", "Sse2", "ShiftRightLogical128BitLane", "Vector128", "Int64", "Vector128", "Int64", "1", "16", "(long)8", "result[0] != 576460752303423488L", "(result[i] != 0)"}),
("ImmUnOpTest.template", new string[] { "Sse2", "Sse2", "ShiftRightLogical128BitLane", "Vector128", "UInt64", "Vector128", "UInt64", "1", "16", "(ulong)8", "result[0] != 576460752303423488UL", "(result[i] != 0)"}),
+ ("ExtractScalarTest.template",new string[] {"Sse2", "Sse2", "Extract", "Vector128", "Int16", "Vector128", "Int16", "1", "16", "(short)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] {"Sse2", "Sse2", "Extract", "Vector128", "UInt16", "Vector128", "UInt16", "1", "16", "(ushort)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] {"Sse2", "Sse2", "Extract", "Vector128", "Int16", "Vector128", "Int16", "129", "16", "(short)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] {"Sse2", "Sse2", "Extract", "Vector128", "UInt16", "Vector128", "UInt16", "129", "16", "(ushort)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("InsertScalarTest.template",new string[] { "Sse2", "Sse2", "Insert", "Vector128", "Int16", "Vector128", "Int16", "1", "(short)2", "16", "(short)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse2", "Sse2", "Insert", "Vector128", "UInt16", "Vector128", "UInt16", "1", "(ushort)2","16", "(ushort)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse2", "Sse2", "Insert", "Vector128", "Int16", "Vector128", "Int16", "129","(short)2", "16", "(short)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse2", "Sse2", "Insert", "Vector128", "UInt16", "Vector128", "UInt16", "129","(ushort)2","16", "(ushort)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
};
private static readonly (string templateFileName, string[] templateData)[] Sse3Inputs = new []
@@ -339,6 +347,36 @@ private static readonly (string templateFileName, string[] templateData)[] Sse41
("BooleanBinOpTest.template", new string[] { "Sse41", "Sse2", "TestZ", "Vector128", "UInt16", "Vector128", "UInt16", "Vector128", "UInt16", "16", "(ushort)(random.Next(0, ushort.MaxValue))", "(ushort)(random.Next(0, ushort.MaxValue))", "(left[i] & right[i]) == 0"}),
("BooleanBinOpTest.template", new string[] { "Sse41", "Sse2", "TestZ", "Vector128", "UInt32", "Vector128", "UInt32", "Vector128", "UInt32", "16", "(uint)(random.Next(0, int.MaxValue))", "(uint)(random.Next(0, int.MaxValue))", "(left[i] & right[i]) == 0"}),
("BooleanBinOpTest.template", new string[] { "Sse41", "Sse2", "TestZ", "Vector128", "UInt64", "Vector128", "UInt64", "Vector128", "UInt64", "16", "(ulong)(random.Next(0, int.MaxValue))", "(ulong)(random.Next(0, int.MaxValue))", "(left[i] & right[i]) == 0"}),
+ // IMM intrinsics
+ // TemplateName Isa, LoadIsa, Method, RetVectorType, RetBaseType, Op1VectorType, Op1BaseType, IMM, Op2 VectorSize, NextValueOp1, ValidateResults
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "Byte", "Vector128", "Byte", "1", "16", "(byte)(random.Next(0, byte.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "SByte", "Vector128", "SByte", "1", "16", "(sbyte)(random.Next(0, sbyte.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "Int32", "Vector128", "Int32", "1", "16", "(int)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "UInt32", "Vector128", "UInt32", "1", "16", "(uint)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "Int64", "Vector128", "Int64", "1", "16", "(long)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "UInt64", "Vector128", "UInt64", "1", "16", "(ulong)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse", "Extract", "Vector128", "Single", "Vector128", "Single", "1", "16", "(float)(random.NextDouble())", "(BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(firstOp[1]))"}),
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "Byte", "Vector128", "Byte", "129", "16", "(byte)(random.Next(0, byte.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "SByte", "Vector128", "SByte", "129", "16", "(sbyte)(random.Next(0, sbyte.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "Int32", "Vector128", "Int32", "129", "16", "(int)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "UInt32", "Vector128", "UInt32", "129", "16", "(uint)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "Int64", "Vector128", "Int64", "129", "16", "(long)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse2", "Extract", "Vector128", "UInt64", "Vector128", "UInt64", "129", "16", "(ulong)(random.Next(0, int.MaxValue))", "(result[0] != firstOp[1])"}),
+ ("ExtractScalarTest.template",new string[] { "Sse41", "Sse", "Extract", "Vector128", "Single", "Vector128", "Single", "129", "16", "(float)(random.NextDouble())", "(BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(firstOp[1]))"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "Byte", "Vector128", "Byte", "1", "(byte)2", "16", "(byte)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "SByte", "Vector128", "SByte", "1", "(sbyte)2", "16", "(sbyte)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "Int32", "Vector128", "Int32", "1", "(int)2", "16", "(int)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "UInt32", "Vector128", "UInt32", "1", "(uint)2", "16", "(uint)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "Int64", "Vector128", "Int64", "1", "(long)2", "16", "(long)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "UInt64", "Vector128", "UInt64", "1", "(ulong)2", "16", "(ulong)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse", "Insert", "Vector128", "Single", "Vector128", "Single", "0", "(float)2", "16", "(float)0", "(i == 0 ? BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((float)2) : BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((float)0))"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "Byte", "Vector128", "Byte", "129", "(byte)2", "16", "(byte)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "SByte", "Vector128", "SByte", "129", "(sbyte)2", "16", "(sbyte)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "Int32", "Vector128", "Int32", "129", "(int)2", "16", "(int)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "UInt32", "Vector128", "UInt32", "129", "(uint)2", "16", "(uint)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "Int64", "Vector128", "Int64", "129", "(long)2", "16", "(long)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse2", "Insert", "Vector128", "UInt64", "Vector128", "UInt64", "129", "(ulong)2", "16", "(ulong)0", "(i == 1 ? result[i] != 2 : result[i] != 0)"}),
+ ("InsertScalarTest.template",new string[] { "Sse41", "Sse", "Insert", "Vector128", "Single", "Vector128", "Single", "217", "(float)2", "16", "(float)(random.NextDouble())", "(i == 2 ? BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i]) : BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((float)0))"}),
};
private static readonly (string templateFileName, string[] templateData)[] Sse42Inputs = new []
@@ -568,7 +606,8 @@ namespace JIT.HardwareIntrinsics.X86
private static bool isImmTemplate(string name)
{
- return name == "ImmUnOpTest.template";
+ return name == "ImmUnOpTest.template" || name == "InsertScalarTest.template" ||
+ name == "ExtractScalarTest.template";
}
private static void ProcessInput(StreamWriter testListFile, (string templateFileName, string[] templateData) input)
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/InsertScalarTest.template b/tests/src/JIT/HardwareIntrinsics/X86/Shared/InsertScalarTest.template
new file mode 100644
index 0000000000..987a2dd6ac
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/InsertScalarTest.template
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 {2}{4}{7}()
+ {{
+ var test = new SimpleUnaryOpTest__{2}{4}{7}();
+
+ try
+ {{
+ if (test.IsSupported)
+ {{
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if ({1}.IsSupported)
+ {{
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }}
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if ({1}.IsSupported)
+ {{
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }}
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if ({1}.IsSupported)
+ {{
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }}
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }}
+ else
+ {{
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }}
+ }}
+ catch (PlatformNotSupportedException)
+ {{
+ test.Succeeded = true;
+ }}
+
+ if (!test.Succeeded)
+ {{
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }}
+ }}
+ }}
+
+ public sealed unsafe class SimpleUnaryOpTest__{2}{4}{7}
+ {{
+ private const int VectorSize = {9};
+
+ private const int Op1ElementCount = VectorSize / sizeof({6});
+ private const int RetElementCount = VectorSize / sizeof({4});
+
+ private static {6}[] _data = new {6}[Op1ElementCount];
+
+ private static {5}<{6}> _clsVar;
+
+ private {5}<{6}> _fld;
+
+ private SimpleUnaryOpTest__DataTable<{4}, {6}> _dataTable;
+
+ static SimpleUnaryOpTest__{2}{4}{7}()
+ {{
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) {{ _data[i] = {10}; }}
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{5}<{6}>, byte>(ref _clsVar), ref Unsafe.As<{6}, byte>(ref _data[0]), VectorSize);
+ }}
+
+ public SimpleUnaryOpTest__{2}{4}{7}()
+ {{
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) {{ _data[i] = {10}; }}
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{5}<{6}>, byte>(ref _fld), ref Unsafe.As<{6}, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) {{ _data[i] = {10}; }}
+ _dataTable = new SimpleUnaryOpTest__DataTable<{4}, {6}>(_data, new {4}[RetElementCount], VectorSize);
+ }}
+
+ public bool IsSupported => {0}.IsSupported;
+
+ public bool Succeeded {{ get; set; }}
+
+ public void RunBasicScenario_UnsafeRead()
+ {{
+ var result = {0}.{2}(
+ Unsafe.Read<{5}<{6}>>(_dataTable.inArrayPtr),
+ {8},
+ {7}
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }}
+
+ public void RunBasicScenario_Load()
+ {{
+ var result = {0}.{2}(
+ {1}.Load{5}(({6}*)(_dataTable.inArrayPtr)),
+ {8},
+ {7}
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }}
+
+ public void RunBasicScenario_LoadAligned()
+ {{
+ var result = {0}.{2}(
+ {1}.LoadAligned{5}(({6}*)(_dataTable.inArrayPtr)),
+ {8},
+ {7}
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }}
+
+ public void RunReflectionScenario_UnsafeRead()
+ {{
+ var result = typeof({0}).GetMethod(nameof({0}.{2}), new Type[] {{ typeof({5}<{6}>), typeof({4}), typeof(byte) }})
+ .Invoke(null, new object[] {{
+ Unsafe.Read<{5}<{6}>>(_dataTable.inArrayPtr),
+ {8},
+ (byte){7}
+ }});
+
+ Unsafe.Write(_dataTable.outArrayPtr, ({3}<{4}>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }}
+
+ public void RunReflectionScenario_Load()
+ {{
+ var result = typeof({0}).GetMethod(nameof({0}.{2}), new Type[] {{ typeof({5}<{6}>), typeof({4}), typeof(byte) }})
+ .Invoke(null, new object[] {{
+ {1}.Load{5}(({6}*)(_dataTable.inArrayPtr)),
+ {8},
+ (byte){7}
+ }});
+
+ Unsafe.Write(_dataTable.outArrayPtr, ({3}<{4}>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }}
+
+ public void RunReflectionScenario_LoadAligned()
+ {{
+ var result = typeof({0}).GetMethod(nameof({0}.{2}), new Type[] {{ typeof({5}<{6}>), typeof({4}), typeof(byte) }})
+ .Invoke(null, new object[] {{
+ {1}.LoadAligned{5}(({6}*)(_dataTable.inArrayPtr)),
+ {8},
+ (byte){7}
+ }});
+
+ Unsafe.Write(_dataTable.outArrayPtr, ({3}<{4}>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }}
+
+ public void RunClsVarScenario()
+ {{
+ var result = {0}.{2}(
+ _clsVar,
+ {8},
+ {7}
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }}
+
+ public void RunLclVarScenario_UnsafeRead()
+ {{
+ var firstOp = Unsafe.Read<{5}<{6}>>(_dataTable.inArrayPtr);
+ var result = {0}.{2}(firstOp, {8}, {7});
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }}
+
+ public void RunLclVarScenario_Load()
+ {{
+ var firstOp = {1}.Load{5}(({6}*)(_dataTable.inArrayPtr));
+ var result = {0}.{2}(firstOp, {8}, {7});
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }}
+
+ public void RunLclVarScenario_LoadAligned()
+ {{
+ var firstOp = {1}.LoadAligned{5}(({6}*)(_dataTable.inArrayPtr));
+ var result = {0}.{2}(firstOp, {8}, {7});
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }}
+
+ public void RunLclFldScenario()
+ {{
+ var test = new SimpleUnaryOpTest__{2}{4}{7}();
+ var result = {0}.{2}(test._fld, {8}, {7});
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }}
+
+ public void RunFldScenario()
+ {{
+ var result = {0}.{2}(_fld, {8}, {7});
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }}
+
+ public void RunUnsupportedScenario()
+ {{
+ Succeeded = false;
+
+ try
+ {{
+ RunBasicScenario_UnsafeRead();
+ }}
+ catch (PlatformNotSupportedException)
+ {{
+ Succeeded = true;
+ }}
+ }}
+
+ private void ValidateResult({5}<{6}> firstOp, void* result, [CallerMemberName] string method = "")
+ {{
+ {6}[] inArray = new {6}[Op1ElementCount];
+ {4}[] outArray = new {4}[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{4}, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }}
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {{
+ {6}[] inArray = new {6}[Op1ElementCount];
+ {4}[] outArray = new {4}[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{6}, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<{4}, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }}
+
+ private void ValidateResult({6}[] firstOp, {4}[] result, [CallerMemberName] string method = "")
+ {{
+
+ for (var i = 0; i < RetElementCount; i++)
+ {{
+ if ({11})
+ {{
+ Succeeded = false;
+ break;
+ }}
+ }}
+
+ if (!Succeeded)
+ {{
+ Console.WriteLine($"{{nameof({0})}}.{{nameof({0}.{2})}}<{4}>({5}<{6}><9>): {{method}} failed:");
+ Console.WriteLine($" firstOp: ({{string.Join(", ", firstOp)}})");
+ Console.WriteLine($" result: ({{string.Join(", ", result)}})");
+ Console.WriteLine();
+ }}
+ }}
+ }}
+}}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.1.cs
new file mode 100644
index 0000000000..3b3c5e1ab5
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.1.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractInt161()
+ {
+ var test = new SimpleUnaryOpTest__ExtractInt161();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractInt161
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Int16);
+ private const int RetElementCount = VectorSize / sizeof(Int16);
+
+ private static Int16[] _data = new Int16[Op1ElementCount];
+
+ private static Vector128<Int16> _clsVar;
+
+ private Vector128<Int16> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Int16, Int16> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractInt161()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractInt161()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Int16, Int16>(_data, new Int16[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse2.Extract(
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse2.Extract(
+ Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse2.Extract(
+ Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<Int16>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int16)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<Int16>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int16)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<Int16>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int16)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Extract(
+ _clsVar,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr);
+ var result = Sse2.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractInt161();
+ var result = Sse2.Extract(test._fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Extract(_fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int16> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray = new Int16[Op1ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray = new Int16[Op1ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Extract)}<Int16>(Vector128<Int16><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.129.cs
new file mode 100644
index 0000000000..3a450f7922
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.Int16.129.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractInt16129()
+ {
+ var test = new SimpleUnaryOpTest__ExtractInt16129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractInt16129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Int16);
+ private const int RetElementCount = VectorSize / sizeof(Int16);
+
+ private static Int16[] _data = new Int16[Op1ElementCount];
+
+ private static Vector128<Int16> _clsVar;
+
+ private Vector128<Int16> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Int16, Int16> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractInt16129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractInt16129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Int16, Int16>(_data, new Int16[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse2.Extract(
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse2.Extract(
+ Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse2.Extract(
+ Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<Int16>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int16)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<Int16>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int16)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<Int16>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int16)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Extract(
+ _clsVar,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr);
+ var result = Sse2.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractInt16129();
+ var result = Sse2.Extract(test._fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Extract(_fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int16> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray = new Int16[Op1ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray = new Int16[Op1ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Extract)}<Int16>(Vector128<Int16><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.1.cs
new file mode 100644
index 0000000000..24487a2dbb
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.1.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractUInt161()
+ {
+ var test = new SimpleUnaryOpTest__ExtractUInt161();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractUInt161
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(UInt16);
+ private const int RetElementCount = VectorSize / sizeof(UInt16);
+
+ private static UInt16[] _data = new UInt16[Op1ElementCount];
+
+ private static Vector128<UInt16> _clsVar;
+
+ private Vector128<UInt16> _fld;
+
+ private SimpleUnaryOpTest__DataTable<UInt16, UInt16> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractUInt161()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractUInt161()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<UInt16, UInt16>(_data, new UInt16[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse2.Extract(
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse2.Extract(
+ Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse2.Extract(
+ Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<UInt16>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt16)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<UInt16>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt16)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<UInt16>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt16)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Extract(
+ _clsVar,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr);
+ var result = Sse2.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractUInt161();
+ var result = Sse2.Extract(test._fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Extract(_fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt16> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray = new UInt16[Op1ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray = new UInt16[Op1ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Extract)}<UInt16>(Vector128<UInt16><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.129.cs
new file mode 100644
index 0000000000..facafddf76
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Extract.UInt16.129.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractUInt16129()
+ {
+ var test = new SimpleUnaryOpTest__ExtractUInt16129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractUInt16129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(UInt16);
+ private const int RetElementCount = VectorSize / sizeof(UInt16);
+
+ private static UInt16[] _data = new UInt16[Op1ElementCount];
+
+ private static Vector128<UInt16> _clsVar;
+
+ private Vector128<UInt16> _fld;
+
+ private SimpleUnaryOpTest__DataTable<UInt16, UInt16> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractUInt16129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractUInt16129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<UInt16, UInt16>(_data, new UInt16[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse2.Extract(
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse2.Extract(
+ Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse2.Extract(
+ Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<UInt16>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt16)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<UInt16>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt16)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Extract), new Type[] { typeof(Vector128<UInt16>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt16)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Extract(
+ _clsVar,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr);
+ var result = Sse2.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractUInt16129();
+ var result = Sse2.Extract(test._fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Extract(_fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt16> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray = new UInt16[Op1ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray = new UInt16[Op1ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Extract)}<UInt16>(Vector128<UInt16><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.1.cs
new file mode 100644
index 0000000000..90d8edb9a6
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.1.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertInt161()
+ {
+ var test = new SimpleUnaryOpTest__InsertInt161();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertInt161
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Int16);
+ private const int RetElementCount = VectorSize / sizeof(Int16);
+
+ private static Int16[] _data = new Int16[Op1ElementCount];
+
+ private static Vector128<Int16> _clsVar;
+
+ private Vector128<Int16> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Int16, Int16> _dataTable;
+
+ static SimpleUnaryOpTest__InsertInt161()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertInt161()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Int16, Int16>(_data, new Int16[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse2.Insert(
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr),
+ (short)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse2.Insert(
+ Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)),
+ (short)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse2.Insert(
+ Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)),
+ (short)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<Int16>), typeof(Int16), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr),
+ (short)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<Int16>), typeof(Int16), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)),
+ (short)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<Int16>), typeof(Int16), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)),
+ (short)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Insert(
+ _clsVar,
+ (short)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr);
+ var result = Sse2.Insert(firstOp, (short)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Insert(firstOp, (short)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Insert(firstOp, (short)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertInt161();
+ var result = Sse2.Insert(test._fld, (short)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Insert(_fld, (short)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int16> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray = new Int16[Op1ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray = new Int16[Op1ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Insert)}<Int16>(Vector128<Int16><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.129.cs
new file mode 100644
index 0000000000..d488389ec3
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.Int16.129.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertInt16129()
+ {
+ var test = new SimpleUnaryOpTest__InsertInt16129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertInt16129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Int16);
+ private const int RetElementCount = VectorSize / sizeof(Int16);
+
+ private static Int16[] _data = new Int16[Op1ElementCount];
+
+ private static Vector128<Int16> _clsVar;
+
+ private Vector128<Int16> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Int16, Int16> _dataTable;
+
+ static SimpleUnaryOpTest__InsertInt16129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _clsVar), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertInt16129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int16>, byte>(ref _fld), ref Unsafe.As<Int16, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (short)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Int16, Int16>(_data, new Int16[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse2.Insert(
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr),
+ (short)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse2.Insert(
+ Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)),
+ (short)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse2.Insert(
+ Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)),
+ (short)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<Int16>), typeof(Int16), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr),
+ (short)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<Int16>), typeof(Int16), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr)),
+ (short)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<Int16>), typeof(Int16), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr)),
+ (short)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int16>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Insert(
+ _clsVar,
+ (short)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Int16>>(_dataTable.inArrayPtr);
+ var result = Sse2.Insert(firstOp, (short)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Int16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Insert(firstOp, (short)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Int16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Insert(firstOp, (short)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertInt16129();
+ var result = Sse2.Insert(test._fld, (short)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Insert(_fld, (short)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int16> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray = new Int16[Op1ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int16[] inArray = new Int16[Op1ElementCount];
+ Int16[] outArray = new Int16[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Int16[] firstOp, Int16[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Insert)}<Int16>(Vector128<Int16><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.1.cs
new file mode 100644
index 0000000000..3f5b2704bd
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.1.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertUInt161()
+ {
+ var test = new SimpleUnaryOpTest__InsertUInt161();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertUInt161
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(UInt16);
+ private const int RetElementCount = VectorSize / sizeof(UInt16);
+
+ private static UInt16[] _data = new UInt16[Op1ElementCount];
+
+ private static Vector128<UInt16> _clsVar;
+
+ private Vector128<UInt16> _fld;
+
+ private SimpleUnaryOpTest__DataTable<UInt16, UInt16> _dataTable;
+
+ static SimpleUnaryOpTest__InsertUInt161()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertUInt161()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<UInt16, UInt16>(_data, new UInt16[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse2.Insert(
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr),
+ (ushort)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse2.Insert(
+ Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)),
+ (ushort)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse2.Insert(
+ Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)),
+ (ushort)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<UInt16>), typeof(UInt16), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr),
+ (ushort)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<UInt16>), typeof(UInt16), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)),
+ (ushort)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<UInt16>), typeof(UInt16), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)),
+ (ushort)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Insert(
+ _clsVar,
+ (ushort)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr);
+ var result = Sse2.Insert(firstOp, (ushort)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Insert(firstOp, (ushort)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Insert(firstOp, (ushort)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertUInt161();
+ var result = Sse2.Insert(test._fld, (ushort)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Insert(_fld, (ushort)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt16> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray = new UInt16[Op1ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray = new UInt16[Op1ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Insert)}<UInt16>(Vector128<UInt16><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.129.cs
new file mode 100644
index 0000000000..09e4c6933d
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Insert.UInt16.129.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertUInt16129()
+ {
+ var test = new SimpleUnaryOpTest__InsertUInt16129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertUInt16129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(UInt16);
+ private const int RetElementCount = VectorSize / sizeof(UInt16);
+
+ private static UInt16[] _data = new UInt16[Op1ElementCount];
+
+ private static Vector128<UInt16> _clsVar;
+
+ private Vector128<UInt16> _fld;
+
+ private SimpleUnaryOpTest__DataTable<UInt16, UInt16> _dataTable;
+
+ static SimpleUnaryOpTest__InsertUInt16129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _clsVar), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertUInt16129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt16>, byte>(ref _fld), ref Unsafe.As<UInt16, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ushort)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<UInt16, UInt16>(_data, new UInt16[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse2.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse2.Insert(
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr),
+ (ushort)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse2.Insert(
+ Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)),
+ (ushort)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse2.Insert(
+ Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)),
+ (ushort)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<UInt16>), typeof(UInt16), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr),
+ (ushort)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<UInt16>), typeof(UInt16), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)),
+ (ushort)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse2).GetMethod(nameof(Sse2.Insert), new Type[] { typeof(Vector128<UInt16>), typeof(UInt16), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)),
+ (ushort)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt16>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse2.Insert(
+ _clsVar,
+ (ushort)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<UInt16>>(_dataTable.inArrayPtr);
+ var result = Sse2.Insert(firstOp, (ushort)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Insert(firstOp, (ushort)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr));
+ var result = Sse2.Insert(firstOp, (ushort)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertUInt16129();
+ var result = Sse2.Insert(test._fld, (ushort)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse2.Insert(_fld, (ushort)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt16> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray = new UInt16[Op1ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt16[] inArray = new UInt16[Op1ElementCount];
+ UInt16[] outArray = new UInt16[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt16, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(UInt16[] firstOp, UInt16[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.Insert)}<UInt16>(Vector128<UInt16><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs
index bbb1468b25..ec23caaa3a 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs
@@ -142,6 +142,14 @@ namespace JIT.HardwareIntrinsics.X86
["ShiftRightLogical128BitLane.UInt32.1"] = ShiftRightLogical128BitLaneUInt321,
["ShiftRightLogical128BitLane.Int64.1"] = ShiftRightLogical128BitLaneInt641,
["ShiftRightLogical128BitLane.UInt64.1"] = ShiftRightLogical128BitLaneUInt641,
+ ["Extract.Int16.1"] = ExtractInt161,
+ ["Extract.UInt16.1"] = ExtractUInt161,
+ ["Extract.Int16.129"] = ExtractInt16129,
+ ["Extract.UInt16.129"] = ExtractUInt16129,
+ ["Insert.Int16.1"] = InsertInt161,
+ ["Insert.UInt16.1"] = InsertUInt161,
+ ["Insert.Int16.129"] = InsertInt16129,
+ ["Insert.UInt16.129"] = InsertUInt16129,
};
}
}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj
index d217e01700..22b99ef26f 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj
@@ -79,6 +79,14 @@
<Compile Include="CompareOrdered.Double.cs" />
<Compile Include="CompareUnordered.Double.cs" />
<Compile Include="Divide.Double.cs" />
+ <Compile Include="Extract.Int16.1.cs" />
+ <Compile Include="Extract.UInt16.1.cs" />
+ <Compile Include="Extract.Int16.129.cs" />
+ <Compile Include="Extract.UInt16.129.cs" />
+ <Compile Include="Insert.Int16.1.cs" />
+ <Compile Include="Insert.UInt16.1.cs" />
+ <Compile Include="Insert.Int16.129.cs" />
+ <Compile Include="Insert.UInt16.129.cs" />
<Compile Include="Max.Double.cs" />
<Compile Include="Max.Byte.cs" />
<Compile Include="Max.Int16.cs" />
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj
index ece9047856..6d96ca6eef 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj
@@ -79,6 +79,14 @@
<Compile Include="CompareOrdered.Double.cs" />
<Compile Include="CompareUnordered.Double.cs" />
<Compile Include="Divide.Double.cs" />
+ <Compile Include="Extract.Int16.1.cs" />
+ <Compile Include="Extract.UInt16.1.cs" />
+ <Compile Include="Extract.Int16.129.cs" />
+ <Compile Include="Extract.UInt16.129.cs" />
+ <Compile Include="Insert.Int16.1.cs" />
+ <Compile Include="Insert.UInt16.1.cs" />
+ <Compile Include="Insert.Int16.129.cs" />
+ <Compile Include="Insert.UInt16.129.cs" />
<Compile Include="Max.Double.cs" />
<Compile Include="Max.Byte.cs" />
<Compile Include="Max.Int16.cs" />
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.1.cs
new file mode 100644
index 0000000000..e5583d322b
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.1.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractByte1()
+ {
+ var test = new SimpleUnaryOpTest__ExtractByte1();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractByte1
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Byte);
+ private const int RetElementCount = VectorSize / sizeof(Byte);
+
+ private static Byte[] _data = new Byte[Op1ElementCount];
+
+ private static Vector128<Byte> _clsVar;
+
+ private Vector128<Byte> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Byte, Byte> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractByte1()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractByte1()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Byte, Byte>(_data, new Byte[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Byte>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Byte)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Byte>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Byte)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Byte>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Byte)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractByte1();
+ var result = Sse41.Extract(test._fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Byte> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray = new Byte[Op1ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray = new Byte[Op1ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Byte>(Vector128<Byte><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.129.cs
new file mode 100644
index 0000000000..9b2072b925
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Byte.129.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractByte129()
+ {
+ var test = new SimpleUnaryOpTest__ExtractByte129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractByte129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Byte);
+ private const int RetElementCount = VectorSize / sizeof(Byte);
+
+ private static Byte[] _data = new Byte[Op1ElementCount];
+
+ private static Vector128<Byte> _clsVar;
+
+ private Vector128<Byte> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Byte, Byte> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractByte129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractByte129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)(random.Next(0, byte.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Byte, Byte>(_data, new Byte[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Byte>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Byte)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Byte>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Byte)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Byte>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Byte)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractByte129();
+ var result = Sse41.Extract(test._fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Byte> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray = new Byte[Op1ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray = new Byte[Op1ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Byte>(Vector128<Byte><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.1.cs
new file mode 100644
index 0000000000..5635609eb4
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.1.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractInt321()
+ {
+ var test = new SimpleUnaryOpTest__ExtractInt321();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractInt321
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Int32);
+ private const int RetElementCount = VectorSize / sizeof(Int32);
+
+ private static Int32[] _data = new Int32[Op1ElementCount];
+
+ private static Vector128<Int32> _clsVar;
+
+ private Vector128<Int32> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Int32, Int32> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractInt321()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractInt321()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Int32, Int32>(_data, new Int32[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int32>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int32)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int32>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int32)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int32>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int32)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractInt321();
+ var result = Sse41.Extract(test._fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int32> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray = new Int32[Op1ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray = new Int32[Op1ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Int32>(Vector128<Int32><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.129.cs
new file mode 100644
index 0000000000..c1e0f4500e
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int32.129.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractInt32129()
+ {
+ var test = new SimpleUnaryOpTest__ExtractInt32129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractInt32129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Int32);
+ private const int RetElementCount = VectorSize / sizeof(Int32);
+
+ private static Int32[] _data = new Int32[Op1ElementCount];
+
+ private static Vector128<Int32> _clsVar;
+
+ private Vector128<Int32> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Int32, Int32> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractInt32129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractInt32129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Int32, Int32>(_data, new Int32[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int32>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int32)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int32>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int32)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int32>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int32)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractInt32129();
+ var result = Sse41.Extract(test._fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int32> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray = new Int32[Op1ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray = new Int32[Op1ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Int32>(Vector128<Int32><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.1.cs
new file mode 100644
index 0000000000..4f4fb7d109
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.1.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractInt641()
+ {
+ var test = new SimpleUnaryOpTest__ExtractInt641();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractInt641
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Int64);
+ private const int RetElementCount = VectorSize / sizeof(Int64);
+
+ private static Int64[] _data = new Int64[Op1ElementCount];
+
+ private static Vector128<Int64> _clsVar;
+
+ private Vector128<Int64> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Int64, Int64> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractInt641()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractInt641()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Int64, Int64>(_data, new Int64[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int64>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int64)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int64>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int64)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int64>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int64)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractInt641();
+ var result = Sse41.Extract(test._fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int64> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Int64>(Vector128<Int64><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.129.cs
new file mode 100644
index 0000000000..15a11cb65e
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Int64.129.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractInt64129()
+ {
+ var test = new SimpleUnaryOpTest__ExtractInt64129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractInt64129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Int64);
+ private const int RetElementCount = VectorSize / sizeof(Int64);
+
+ private static Int64[] _data = new Int64[Op1ElementCount];
+
+ private static Vector128<Int64> _clsVar;
+
+ private Vector128<Int64> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Int64, Int64> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractInt64129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractInt64129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Int64, Int64>(_data, new Int64[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int64>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int64)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int64>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int64)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Int64>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Int64)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractInt64129();
+ var result = Sse41.Extract(test._fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int64> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Int64>(Vector128<Int64><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.1.cs
new file mode 100644
index 0000000000..73bd616b67
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.1.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractSByte1()
+ {
+ var test = new SimpleUnaryOpTest__ExtractSByte1();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractSByte1
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(SByte);
+ private const int RetElementCount = VectorSize / sizeof(SByte);
+
+ private static SByte[] _data = new SByte[Op1ElementCount];
+
+ private static Vector128<SByte> _clsVar;
+
+ private Vector128<SByte> _fld;
+
+ private SimpleUnaryOpTest__DataTable<SByte, SByte> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractSByte1()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractSByte1()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<SByte, SByte>(_data, new SByte[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<SByte>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (SByte)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<SByte>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (SByte)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<SByte>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (SByte)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractSByte1();
+ var result = Sse41.Extract(test._fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<SByte> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<SByte>(Vector128<SByte><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.129.cs
new file mode 100644
index 0000000000..219bdc47ab
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.SByte.129.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractSByte129()
+ {
+ var test = new SimpleUnaryOpTest__ExtractSByte129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractSByte129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(SByte);
+ private const int RetElementCount = VectorSize / sizeof(SByte);
+
+ private static SByte[] _data = new SByte[Op1ElementCount];
+
+ private static Vector128<SByte> _clsVar;
+
+ private Vector128<SByte> _fld;
+
+ private SimpleUnaryOpTest__DataTable<SByte, SByte> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractSByte129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractSByte129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)(random.Next(0, sbyte.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<SByte, SByte>(_data, new SByte[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<SByte>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (SByte)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<SByte>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (SByte)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<SByte>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (SByte)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractSByte129();
+ var result = Sse41.Extract(test._fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<SByte> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<SByte>(Vector128<SByte><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.1.cs
new file mode 100644
index 0000000000..4315fda964
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.1.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractSingle1()
+ {
+ var test = new SimpleUnaryOpTest__ExtractSingle1();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractSingle1
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Single);
+ private const int RetElementCount = VectorSize / sizeof(Single);
+
+ private static Single[] _data = new Single[Op1ElementCount];
+
+ private static Vector128<Single> _clsVar;
+
+ private Vector128<Single> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Single, Single> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractSingle1()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractSingle1()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Single, Single>(_data, new Single[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Single>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Single)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Single>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Single)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Single>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Single)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse.LoadVector128((Single*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractSingle1();
+ var result = Sse41.Extract(test._fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Single> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "")
+ {
+ if ((BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(firstOp[1])))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Single>(Vector128<Single><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.129.cs
new file mode 100644
index 0000000000..78b40d049c
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.Single.129.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractSingle129()
+ {
+ var test = new SimpleUnaryOpTest__ExtractSingle129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractSingle129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Single);
+ private const int RetElementCount = VectorSize / sizeof(Single);
+
+ private static Single[] _data = new Single[Op1ElementCount];
+
+ private static Vector128<Single> _clsVar;
+
+ private Vector128<Single> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Single, Single> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractSingle129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractSingle129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Single, Single>(_data, new Single[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Single>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Single)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Single>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Single)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<Single>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Single)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse.LoadVector128((Single*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractSingle129();
+ var result = Sse41.Extract(test._fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Single> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "")
+ {
+ if ((BitConverter.SingleToInt32Bits(result[0]) != BitConverter.SingleToInt32Bits(firstOp[1])))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<Single>(Vector128<Single><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.1.cs
new file mode 100644
index 0000000000..1545207481
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.1.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractUInt321()
+ {
+ var test = new SimpleUnaryOpTest__ExtractUInt321();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractUInt321
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(UInt32);
+ private const int RetElementCount = VectorSize / sizeof(UInt32);
+
+ private static UInt32[] _data = new UInt32[Op1ElementCount];
+
+ private static Vector128<UInt32> _clsVar;
+
+ private Vector128<UInt32> _fld;
+
+ private SimpleUnaryOpTest__DataTable<UInt32, UInt32> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractUInt321()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractUInt321()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<UInt32, UInt32>(_data, new UInt32[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt32>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt32)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt32>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt32)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt32>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt32)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractUInt321();
+ var result = Sse41.Extract(test._fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt32> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray = new UInt32[Op1ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray = new UInt32[Op1ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<UInt32>(Vector128<UInt32><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.129.cs
new file mode 100644
index 0000000000..3d38f36744
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt32.129.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractUInt32129()
+ {
+ var test = new SimpleUnaryOpTest__ExtractUInt32129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractUInt32129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(UInt32);
+ private const int RetElementCount = VectorSize / sizeof(UInt32);
+
+ private static UInt32[] _data = new UInt32[Op1ElementCount];
+
+ private static Vector128<UInt32> _clsVar;
+
+ private Vector128<UInt32> _fld;
+
+ private SimpleUnaryOpTest__DataTable<UInt32, UInt32> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractUInt32129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractUInt32129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<UInt32, UInt32>(_data, new UInt32[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt32>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt32)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt32>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt32)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt32>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt32)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractUInt32129();
+ var result = Sse41.Extract(test._fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt32> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray = new UInt32[Op1ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray = new UInt32[Op1ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<UInt32>(Vector128<UInt32><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.1.cs
new file mode 100644
index 0000000000..f7e3300162
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.1.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractUInt641()
+ {
+ var test = new SimpleUnaryOpTest__ExtractUInt641();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractUInt641
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(UInt64);
+ private const int RetElementCount = VectorSize / sizeof(UInt64);
+
+ private static UInt64[] _data = new UInt64[Op1ElementCount];
+
+ private static Vector128<UInt64> _clsVar;
+
+ private Vector128<UInt64> _fld;
+
+ private SimpleUnaryOpTest__DataTable<UInt64, UInt64> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractUInt641()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractUInt641()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<UInt64, UInt64>(_data, new UInt64[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)),
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt64>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt64)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt64>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt64)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt64>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)),
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt64)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractUInt641();
+ var result = Sse41.Extract(test._fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt64> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray = new UInt64[Op1ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray = new UInt64[Op1ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<UInt64>(Vector128<UInt64><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.129.cs
new file mode 100644
index 0000000000..53d42020da
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Extract.UInt64.129.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more 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 ExtractUInt64129()
+ {
+ var test = new SimpleUnaryOpTest__ExtractUInt64129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__ExtractUInt64129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(UInt64);
+ private const int RetElementCount = VectorSize / sizeof(UInt64);
+
+ private static UInt64[] _data = new UInt64[Op1ElementCount];
+
+ private static Vector128<UInt64> _clsVar;
+
+ private Vector128<UInt64> _fld;
+
+ private SimpleUnaryOpTest__DataTable<UInt64, UInt64> _dataTable;
+
+ static SimpleUnaryOpTest__ExtractUInt64129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__ExtractUInt64129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)(random.Next(0, int.MaxValue)); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<UInt64, UInt64>(_data, new UInt64[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Extract(
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Extract(
+ Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)),
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt64>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt64)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt64>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt64)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Extract), new Type[] { typeof(Vector128<UInt64>), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)),
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (UInt64)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Extract(
+ _clsVar,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr);
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Extract(firstOp, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__ExtractUInt64129();
+ var result = Sse41.Extract(test._fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Extract(_fld, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt64> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray = new UInt64[Op1ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray = new UInt64[Op1ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "")
+ {
+ if ((result[0] != firstOp[1]))
+ {
+ Succeeded = false;
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Extract)}<UInt64>(Vector128<UInt64><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.1.cs
new file mode 100644
index 0000000000..173d44e91f
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.1.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertByte1()
+ {
+ var test = new SimpleUnaryOpTest__InsertByte1();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertByte1
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Byte);
+ private const int RetElementCount = VectorSize / sizeof(Byte);
+
+ private static Byte[] _data = new Byte[Op1ElementCount];
+
+ private static Vector128<Byte> _clsVar;
+
+ private Vector128<Byte> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Byte, Byte> _dataTable;
+
+ static SimpleUnaryOpTest__InsertByte1()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertByte1()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Byte, Byte>(_data, new Byte[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr),
+ (byte)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)),
+ (byte)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)),
+ (byte)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Byte>), typeof(Byte), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr),
+ (byte)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Byte>), typeof(Byte), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)),
+ (byte)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Byte>), typeof(Byte), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)),
+ (byte)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (byte)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (byte)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (byte)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (byte)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertByte1();
+ var result = Sse41.Insert(test._fld, (byte)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (byte)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Byte> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray = new Byte[Op1ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray = new Byte[Op1ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Byte>(Vector128<Byte><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.129.cs
new file mode 100644
index 0000000000..26d0b8ab47
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Byte.129.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertByte129()
+ {
+ var test = new SimpleUnaryOpTest__InsertByte129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertByte129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Byte);
+ private const int RetElementCount = VectorSize / sizeof(Byte);
+
+ private static Byte[] _data = new Byte[Op1ElementCount];
+
+ private static Vector128<Byte> _clsVar;
+
+ private Vector128<Byte> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Byte, Byte> _dataTable;
+
+ static SimpleUnaryOpTest__InsertByte129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _clsVar), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertByte129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Byte>, byte>(ref _fld), ref Unsafe.As<Byte, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (byte)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Byte, Byte>(_data, new Byte[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr),
+ (byte)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)),
+ (byte)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)),
+ (byte)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Byte>), typeof(Byte), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr),
+ (byte)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Byte>), typeof(Byte), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)),
+ (byte)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Byte>), typeof(Byte), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)),
+ (byte)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Byte>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (byte)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Byte>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (byte)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (byte)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (byte)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertByte129();
+ var result = Sse41.Insert(test._fld, (byte)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (byte)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Byte> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray = new Byte[Op1ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Byte[] inArray = new Byte[Op1ElementCount];
+ Byte[] outArray = new Byte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Byte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Byte[] firstOp, Byte[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Byte>(Vector128<Byte><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.1.cs
new file mode 100644
index 0000000000..404cbb56a0
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.1.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertInt321()
+ {
+ var test = new SimpleUnaryOpTest__InsertInt321();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertInt321
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Int32);
+ private const int RetElementCount = VectorSize / sizeof(Int32);
+
+ private static Int32[] _data = new Int32[Op1ElementCount];
+
+ private static Vector128<Int32> _clsVar;
+
+ private Vector128<Int32> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Int32, Int32> _dataTable;
+
+ static SimpleUnaryOpTest__InsertInt321()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertInt321()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Int32, Int32>(_data, new Int32[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr),
+ (int)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)),
+ (int)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)),
+ (int)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int32>), typeof(Int32), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr),
+ (int)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int32>), typeof(Int32), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)),
+ (int)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int32>), typeof(Int32), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)),
+ (int)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (int)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (int)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (int)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (int)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertInt321();
+ var result = Sse41.Insert(test._fld, (int)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (int)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int32> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray = new Int32[Op1ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray = new Int32[Op1ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Int32>(Vector128<Int32><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.129.cs
new file mode 100644
index 0000000000..d5d09c4d04
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int32.129.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertInt32129()
+ {
+ var test = new SimpleUnaryOpTest__InsertInt32129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertInt32129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Int32);
+ private const int RetElementCount = VectorSize / sizeof(Int32);
+
+ private static Int32[] _data = new Int32[Op1ElementCount];
+
+ private static Vector128<Int32> _clsVar;
+
+ private Vector128<Int32> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Int32, Int32> _dataTable;
+
+ static SimpleUnaryOpTest__InsertInt32129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _clsVar), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertInt32129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int32>, byte>(ref _fld), ref Unsafe.As<Int32, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (int)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Int32, Int32>(_data, new Int32[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr),
+ (int)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)),
+ (int)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)),
+ (int)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int32>), typeof(Int32), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr),
+ (int)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int32>), typeof(Int32), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr)),
+ (int)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int32>), typeof(Int32), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr)),
+ (int)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int32>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (int)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Int32>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (int)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Int32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (int)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Int32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (int)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertInt32129();
+ var result = Sse41.Insert(test._fld, (int)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (int)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int32> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray = new Int32[Op1ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int32[] inArray = new Int32[Op1ElementCount];
+ Int32[] outArray = new Int32[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Int32[] firstOp, Int32[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Int32>(Vector128<Int32><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.1.cs
new file mode 100644
index 0000000000..ff48f25b03
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.1.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertInt641()
+ {
+ var test = new SimpleUnaryOpTest__InsertInt641();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertInt641
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Int64);
+ private const int RetElementCount = VectorSize / sizeof(Int64);
+
+ private static Int64[] _data = new Int64[Op1ElementCount];
+
+ private static Vector128<Int64> _clsVar;
+
+ private Vector128<Int64> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Int64, Int64> _dataTable;
+
+ static SimpleUnaryOpTest__InsertInt641()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertInt641()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Int64, Int64>(_data, new Int64[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr),
+ (long)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)),
+ (long)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)),
+ (long)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int64>), typeof(Int64), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr),
+ (long)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int64>), typeof(Int64), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)),
+ (long)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int64>), typeof(Int64), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)),
+ (long)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (long)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (long)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (long)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (long)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertInt641();
+ var result = Sse41.Insert(test._fld, (long)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (long)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int64> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Int64>(Vector128<Int64><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.129.cs
new file mode 100644
index 0000000000..ff396b3fe1
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Int64.129.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertInt64129()
+ {
+ var test = new SimpleUnaryOpTest__InsertInt64129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertInt64129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Int64);
+ private const int RetElementCount = VectorSize / sizeof(Int64);
+
+ private static Int64[] _data = new Int64[Op1ElementCount];
+
+ private static Vector128<Int64> _clsVar;
+
+ private Vector128<Int64> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Int64, Int64> _dataTable;
+
+ static SimpleUnaryOpTest__InsertInt64129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _clsVar), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertInt64129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Int64>, byte>(ref _fld), ref Unsafe.As<Int64, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (long)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Int64, Int64>(_data, new Int64[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr),
+ (long)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)),
+ (long)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)),
+ (long)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int64>), typeof(Int64), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr),
+ (long)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int64>), typeof(Int64), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr)),
+ (long)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Int64>), typeof(Int64), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr)),
+ (long)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Int64>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (long)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Int64>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (long)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((Int64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (long)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((Int64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (long)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertInt64129();
+ var result = Sse41.Insert(test._fld, (long)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (long)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Int64> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Int64[] inArray = new Int64[Op1ElementCount];
+ Int64[] outArray = new Int64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Int64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Int64[] firstOp, Int64[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Int64>(Vector128<Int64><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.1.cs
new file mode 100644
index 0000000000..bec049220f
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.1.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertSByte1()
+ {
+ var test = new SimpleUnaryOpTest__InsertSByte1();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertSByte1
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(SByte);
+ private const int RetElementCount = VectorSize / sizeof(SByte);
+
+ private static SByte[] _data = new SByte[Op1ElementCount];
+
+ private static Vector128<SByte> _clsVar;
+
+ private Vector128<SByte> _fld;
+
+ private SimpleUnaryOpTest__DataTable<SByte, SByte> _dataTable;
+
+ static SimpleUnaryOpTest__InsertSByte1()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertSByte1()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<SByte, SByte>(_data, new SByte[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr),
+ (sbyte)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)),
+ (sbyte)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)),
+ (sbyte)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<SByte>), typeof(SByte), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr),
+ (sbyte)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<SByte>), typeof(SByte), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)),
+ (sbyte)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<SByte>), typeof(SByte), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)),
+ (sbyte)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (sbyte)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (sbyte)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (sbyte)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (sbyte)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertSByte1();
+ var result = Sse41.Insert(test._fld, (sbyte)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (sbyte)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<SByte> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<SByte>(Vector128<SByte><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.129.cs
new file mode 100644
index 0000000000..d1c339b99c
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.SByte.129.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertSByte129()
+ {
+ var test = new SimpleUnaryOpTest__InsertSByte129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertSByte129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(SByte);
+ private const int RetElementCount = VectorSize / sizeof(SByte);
+
+ private static SByte[] _data = new SByte[Op1ElementCount];
+
+ private static Vector128<SByte> _clsVar;
+
+ private Vector128<SByte> _fld;
+
+ private SimpleUnaryOpTest__DataTable<SByte, SByte> _dataTable;
+
+ static SimpleUnaryOpTest__InsertSByte129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _clsVar), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertSByte129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<SByte>, byte>(ref _fld), ref Unsafe.As<SByte, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (sbyte)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<SByte, SByte>(_data, new SByte[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr),
+ (sbyte)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)),
+ (sbyte)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)),
+ (sbyte)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<SByte>), typeof(SByte), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr),
+ (sbyte)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<SByte>), typeof(SByte), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr)),
+ (sbyte)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<SByte>), typeof(SByte), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr)),
+ (sbyte)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<SByte>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (sbyte)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<SByte>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (sbyte)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((SByte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (sbyte)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((SByte*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (sbyte)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertSByte129();
+ var result = Sse41.Insert(test._fld, (sbyte)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (sbyte)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<SByte> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ SByte[] inArray = new SByte[Op1ElementCount];
+ SByte[] outArray = new SByte[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<SByte, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(SByte[] firstOp, SByte[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<SByte>(Vector128<SByte><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.0.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.0.cs
new file mode 100644
index 0000000000..294fb0ecb9
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.0.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertSingle0()
+ {
+ var test = new SimpleUnaryOpTest__InsertSingle0();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertSingle0
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Single);
+ private const int RetElementCount = VectorSize / sizeof(Single);
+
+ private static Single[] _data = new Single[Op1ElementCount];
+
+ private static Vector128<Single> _clsVar;
+
+ private Vector128<Single> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Single, Single> _dataTable;
+
+ static SimpleUnaryOpTest__InsertSingle0()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertSingle0()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Single, Single>(_data, new Single[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr),
+ (float)2,
+ 0
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)),
+ (float)2,
+ 0
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)),
+ (float)2,
+ 0
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Single>), typeof(Single), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr),
+ (float)2,
+ (byte)0
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Single>), typeof(Single), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)),
+ (float)2,
+ (byte)0
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Single>), typeof(Single), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)),
+ (float)2,
+ (byte)0
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (float)2,
+ 0
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (float)2, 0);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse.LoadVector128((Single*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (float)2, 0);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (float)2, 0);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertSingle0();
+ var result = Sse41.Insert(test._fld, (float)2, 0);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (float)2, 0);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Single> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 0 ? BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((float)2) : BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((float)0)))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Single>(Vector128<Single><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.217.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.217.cs
new file mode 100644
index 0000000000..7b3fcc762c
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.Single.217.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertSingle217()
+ {
+ var test = new SimpleUnaryOpTest__InsertSingle217();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertSingle217
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(Single);
+ private const int RetElementCount = VectorSize / sizeof(Single);
+
+ private static Single[] _data = new Single[Op1ElementCount];
+
+ private static Vector128<Single> _clsVar;
+
+ private Vector128<Single> _fld;
+
+ private SimpleUnaryOpTest__DataTable<Single, Single> _dataTable;
+
+ static SimpleUnaryOpTest__InsertSingle217()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _clsVar), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertSingle217()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Single>, byte>(ref _fld), ref Unsafe.As<Single, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (float)(random.NextDouble()); }
+ _dataTable = new SimpleUnaryOpTest__DataTable<Single, Single>(_data, new Single[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr),
+ (float)2,
+ 217
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)),
+ (float)2,
+ 217
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)),
+ (float)2,
+ 217
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Single>), typeof(Single), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr),
+ (float)2,
+ (byte)217
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Single>), typeof(Single), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse.LoadVector128((Single*)(_dataTable.inArrayPtr)),
+ (float)2,
+ (byte)217
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<Single>), typeof(Single), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr)),
+ (float)2,
+ (byte)217
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Single>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (float)2,
+ 217
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<Single>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (float)2, 217);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse.LoadVector128((Single*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (float)2, 217);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse.LoadAlignedVector128((Single*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (float)2, 217);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertSingle217();
+ var result = Sse41.Insert(test._fld, (float)2, 217);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (float)2, 217);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<Single> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ Single[] inArray = new Single[Op1ElementCount];
+ Single[] outArray = new Single[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(Single[] firstOp, Single[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 2 ? BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits(firstOp[i]) : BitConverter.SingleToInt32Bits(result[i]) != BitConverter.SingleToInt32Bits((float)0)))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<Single>(Vector128<Single><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.1.cs
new file mode 100644
index 0000000000..4568cc8916
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.1.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertUInt321()
+ {
+ var test = new SimpleUnaryOpTest__InsertUInt321();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertUInt321
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(UInt32);
+ private const int RetElementCount = VectorSize / sizeof(UInt32);
+
+ private static UInt32[] _data = new UInt32[Op1ElementCount];
+
+ private static Vector128<UInt32> _clsVar;
+
+ private Vector128<UInt32> _fld;
+
+ private SimpleUnaryOpTest__DataTable<UInt32, UInt32> _dataTable;
+
+ static SimpleUnaryOpTest__InsertUInt321()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertUInt321()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<UInt32, UInt32>(_data, new UInt32[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr),
+ (uint)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)),
+ (uint)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)),
+ (uint)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt32>), typeof(UInt32), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr),
+ (uint)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt32>), typeof(UInt32), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)),
+ (uint)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt32>), typeof(UInt32), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)),
+ (uint)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (uint)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (uint)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (uint)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (uint)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertUInt321();
+ var result = Sse41.Insert(test._fld, (uint)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (uint)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt32> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray = new UInt32[Op1ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray = new UInt32[Op1ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<UInt32>(Vector128<UInt32><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.129.cs
new file mode 100644
index 0000000000..060909cbfe
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt32.129.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertUInt32129()
+ {
+ var test = new SimpleUnaryOpTest__InsertUInt32129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertUInt32129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(UInt32);
+ private const int RetElementCount = VectorSize / sizeof(UInt32);
+
+ private static UInt32[] _data = new UInt32[Op1ElementCount];
+
+ private static Vector128<UInt32> _clsVar;
+
+ private Vector128<UInt32> _fld;
+
+ private SimpleUnaryOpTest__DataTable<UInt32, UInt32> _dataTable;
+
+ static SimpleUnaryOpTest__InsertUInt32129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _clsVar), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertUInt32129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt32>, byte>(ref _fld), ref Unsafe.As<UInt32, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (uint)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<UInt32, UInt32>(_data, new UInt32[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr),
+ (uint)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)),
+ (uint)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)),
+ (uint)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt32>), typeof(UInt32), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr),
+ (uint)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt32>), typeof(UInt32), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)),
+ (uint)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt32>), typeof(UInt32), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)),
+ (uint)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt32>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (uint)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<UInt32>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (uint)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (uint)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (uint)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertUInt32129();
+ var result = Sse41.Insert(test._fld, (uint)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (uint)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt32> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray = new UInt32[Op1ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt32[] inArray = new UInt32[Op1ElementCount];
+ UInt32[] outArray = new UInt32[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt32, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(UInt32[] firstOp, UInt32[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<UInt32>(Vector128<UInt32><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.1.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.1.cs
new file mode 100644
index 0000000000..966c3ab247
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.1.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertUInt641()
+ {
+ var test = new SimpleUnaryOpTest__InsertUInt641();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertUInt641
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(UInt64);
+ private const int RetElementCount = VectorSize / sizeof(UInt64);
+
+ private static UInt64[] _data = new UInt64[Op1ElementCount];
+
+ private static Vector128<UInt64> _clsVar;
+
+ private Vector128<UInt64> _fld;
+
+ private SimpleUnaryOpTest__DataTable<UInt64, UInt64> _dataTable;
+
+ static SimpleUnaryOpTest__InsertUInt641()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertUInt641()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<UInt64, UInt64>(_data, new UInt64[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr),
+ (ulong)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)),
+ (ulong)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)),
+ (ulong)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt64>), typeof(UInt64), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr),
+ (ulong)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt64>), typeof(UInt64), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)),
+ (ulong)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt64>), typeof(UInt64), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)),
+ (ulong)2,
+ (byte)1
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (ulong)2,
+ 1
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (ulong)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (ulong)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (ulong)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertUInt641();
+ var result = Sse41.Insert(test._fld, (ulong)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (ulong)2, 1);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt64> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray = new UInt64[Op1ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray = new UInt64[Op1ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<UInt64>(Vector128<UInt64><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.129.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.129.cs
new file mode 100644
index 0000000000..2ad20b9637
--- /dev/null
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Insert.UInt64.129.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more 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 InsertUInt64129()
+ {
+ var test = new SimpleUnaryOpTest__InsertUInt64129();
+
+ try
+ {
+ if (test.IsSupported)
+ {
+ // Validates basic functionality works, using Unsafe.Read
+ test.RunBasicScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates basic functionality works, using Load
+ test.RunBasicScenario_Load();
+
+ // Validates basic functionality works, using LoadAligned
+ test.RunBasicScenario_LoadAligned();
+ }
+
+ // Validates calling via reflection works, using Unsafe.Read
+ test.RunReflectionScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates calling via reflection works, using Load
+ test.RunReflectionScenario_Load();
+
+ // Validates calling via reflection works, using LoadAligned
+ test.RunReflectionScenario_LoadAligned();
+ }
+
+ // Validates passing a static member works
+ test.RunClsVarScenario();
+
+ // Validates passing a local works, using Unsafe.Read
+ test.RunLclVarScenario_UnsafeRead();
+
+ if (Sse2.IsSupported)
+ {
+ // Validates passing a local works, using Load
+ test.RunLclVarScenario_Load();
+
+ // Validates passing a local works, using LoadAligned
+ test.RunLclVarScenario_LoadAligned();
+ }
+
+ // Validates passing the field of a local works
+ test.RunLclFldScenario();
+
+ // Validates passing an instance member works
+ test.RunFldScenario();
+ }
+ else
+ {
+ // Validates we throw on unsupported hardware
+ test.RunUnsupportedScenario();
+ }
+ }
+ catch (PlatformNotSupportedException)
+ {
+ test.Succeeded = true;
+ }
+
+ if (!test.Succeeded)
+ {
+ throw new Exception("One or more scenarios did not complete as expected.");
+ }
+ }
+ }
+
+ public sealed unsafe class SimpleUnaryOpTest__InsertUInt64129
+ {
+ private const int VectorSize = 16;
+
+ private const int Op1ElementCount = VectorSize / sizeof(UInt64);
+ private const int RetElementCount = VectorSize / sizeof(UInt64);
+
+ private static UInt64[] _data = new UInt64[Op1ElementCount];
+
+ private static Vector128<UInt64> _clsVar;
+
+ private Vector128<UInt64> _fld;
+
+ private SimpleUnaryOpTest__DataTable<UInt64, UInt64> _dataTable;
+
+ static SimpleUnaryOpTest__InsertUInt64129()
+ {
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _clsVar), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize);
+ }
+
+ public SimpleUnaryOpTest__InsertUInt64129()
+ {
+ Succeeded = true;
+
+ var random = new Random();
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)0; }
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<UInt64>, byte>(ref _fld), ref Unsafe.As<UInt64, byte>(ref _data[0]), VectorSize);
+
+ for (var i = 0; i < Op1ElementCount; i++) { _data[i] = (ulong)0; }
+ _dataTable = new SimpleUnaryOpTest__DataTable<UInt64, UInt64>(_data, new UInt64[RetElementCount], VectorSize);
+ }
+
+ public bool IsSupported => Sse41.IsSupported;
+
+ public bool Succeeded { get; set; }
+
+ public void RunBasicScenario_UnsafeRead()
+ {
+ var result = Sse41.Insert(
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr),
+ (ulong)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_Load()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)),
+ (ulong)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunBasicScenario_LoadAligned()
+ {
+ var result = Sse41.Insert(
+ Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)),
+ (ulong)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_UnsafeRead()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt64>), typeof(UInt64), typeof(byte) })
+ .Invoke(null, new object[] {
+ Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr),
+ (ulong)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_Load()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt64>), typeof(UInt64), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr)),
+ (ulong)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunReflectionScenario_LoadAligned()
+ {
+ var result = typeof(Sse41).GetMethod(nameof(Sse41.Insert), new Type[] { typeof(Vector128<UInt64>), typeof(UInt64), typeof(byte) })
+ .Invoke(null, new object[] {
+ Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr)),
+ (ulong)2,
+ (byte)129
+ });
+
+ Unsafe.Write(_dataTable.outArrayPtr, (Vector128<UInt64>)(result));
+ ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr);
+ }
+
+ public void RunClsVarScenario()
+ {
+ var result = Sse41.Insert(
+ _clsVar,
+ (ulong)2,
+ 129
+ );
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_clsVar, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_UnsafeRead()
+ {
+ var firstOp = Unsafe.Read<Vector128<UInt64>>(_dataTable.inArrayPtr);
+ var result = Sse41.Insert(firstOp, (ulong)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_Load()
+ {
+ var firstOp = Sse2.LoadVector128((UInt64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (ulong)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclVarScenario_LoadAligned()
+ {
+ var firstOp = Sse2.LoadAlignedVector128((UInt64*)(_dataTable.inArrayPtr));
+ var result = Sse41.Insert(firstOp, (ulong)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(firstOp, _dataTable.outArrayPtr);
+ }
+
+ public void RunLclFldScenario()
+ {
+ var test = new SimpleUnaryOpTest__InsertUInt64129();
+ var result = Sse41.Insert(test._fld, (ulong)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(test._fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunFldScenario()
+ {
+ var result = Sse41.Insert(_fld, (ulong)2, 129);
+
+ Unsafe.Write(_dataTable.outArrayPtr, result);
+ ValidateResult(_fld, _dataTable.outArrayPtr);
+ }
+
+ public void RunUnsupportedScenario()
+ {
+ Succeeded = false;
+
+ try
+ {
+ RunBasicScenario_UnsafeRead();
+ }
+ catch (PlatformNotSupportedException)
+ {
+ Succeeded = true;
+ }
+ }
+
+ private void ValidateResult(Vector128<UInt64> firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray = new UInt64[Op1ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.Write(Unsafe.AsPointer(ref inArray[0]), firstOp);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(void* firstOp, void* result, [CallerMemberName] string method = "")
+ {
+ UInt64[] inArray = new UInt64[Op1ElementCount];
+ UInt64[] outArray = new UInt64[RetElementCount];
+
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref inArray[0]), ref Unsafe.AsRef<byte>(firstOp), VectorSize);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<UInt64, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
+
+ ValidateResult(inArray, outArray, method);
+ }
+
+ private void ValidateResult(UInt64[] firstOp, UInt64[] result, [CallerMemberName] string method = "")
+ {
+
+ for (var i = 0; i < RetElementCount; i++)
+ {
+ if ((i == 1 ? result[i] != 2 : result[i] != 0))
+ {
+ Succeeded = false;
+ break;
+ }
+ }
+
+ if (!Succeeded)
+ {
+ Console.WriteLine($"{nameof(Sse41)}.{nameof(Sse41.Insert)}<UInt64>(Vector128<UInt64><9>): {method} failed:");
+ Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
+ Console.WriteLine($" result: ({string.Join(", ", result)})");
+ Console.WriteLine();
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Program.Sse41.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Program.Sse41.cs
index c941543373..6e56c9f2f4 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Program.Sse41.cs
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Program.Sse41.cs
@@ -104,6 +104,34 @@ namespace JIT.HardwareIntrinsics.X86
["TestZ.UInt16"] = TestZUInt16,
["TestZ.UInt32"] = TestZUInt32,
["TestZ.UInt64"] = TestZUInt64,
+ ["Extract.Byte.1"] = ExtractByte1,
+ ["Extract.SByte.1"] = ExtractSByte1,
+ ["Extract.Int32.1"] = ExtractInt321,
+ ["Extract.UInt32.1"] = ExtractUInt321,
+ ["Extract.Int64.1"] = ExtractInt641,
+ ["Extract.UInt64.1"] = ExtractUInt641,
+ ["Extract.Single.1"] = ExtractSingle1,
+ ["Extract.Byte.129"] = ExtractByte129,
+ ["Extract.SByte.129"] = ExtractSByte129,
+ ["Extract.Int32.129"] = ExtractInt32129,
+ ["Extract.UInt32.129"] = ExtractUInt32129,
+ ["Extract.Int64.129"] = ExtractInt64129,
+ ["Extract.UInt64.129"] = ExtractUInt64129,
+ ["Extract.Single.129"] = ExtractSingle129,
+ ["Insert.Byte.1"] = InsertByte1,
+ ["Insert.SByte.1"] = InsertSByte1,
+ ["Insert.Int32.1"] = InsertInt321,
+ ["Insert.UInt32.1"] = InsertUInt321,
+ ["Insert.Int64.1"] = InsertInt641,
+ ["Insert.UInt64.1"] = InsertUInt641,
+ ["Insert.Single.0"] = InsertSingle0,
+ ["Insert.Byte.129"] = InsertByte129,
+ ["Insert.SByte.129"] = InsertSByte129,
+ ["Insert.Int32.129"] = InsertInt32129,
+ ["Insert.UInt32.129"] = InsertUInt32129,
+ ["Insert.Int64.129"] = InsertInt64129,
+ ["Insert.UInt64.129"] = InsertUInt64129,
+ ["Insert.Single.217"] = InsertSingle217,
};
}
}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_r.csproj
index 158e94a27d..12a6b0b10d 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_r.csproj
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_r.csproj
@@ -119,6 +119,34 @@
<Compile Include="TestZ.UInt16.cs" />
<Compile Include="TestZ.UInt32.cs" />
<Compile Include="TestZ.UInt64.cs" />
+ <Compile Include="Extract.Byte.1.cs" />
+ <Compile Include="Extract.SByte.1.cs" />
+ <Compile Include="Extract.Int32.1.cs" />
+ <Compile Include="Extract.UInt32.1.cs" />
+ <Compile Include="Extract.Int64.1.cs" />
+ <Compile Include="Extract.UInt64.1.cs" />
+ <Compile Include="Extract.Single.1.cs" />
+ <Compile Include="Extract.Byte.129.cs" />
+ <Compile Include="Extract.SByte.129.cs" />
+ <Compile Include="Extract.Int32.129.cs" />
+ <Compile Include="Extract.UInt32.129.cs" />
+ <Compile Include="Extract.Int64.129.cs" />
+ <Compile Include="Extract.UInt64.129.cs" />
+ <Compile Include="Extract.Single.129.cs" />
+ <Compile Include="Insert.Byte.1.cs" />
+ <Compile Include="Insert.SByte.1.cs" />
+ <Compile Include="Insert.Int32.1.cs" />
+ <Compile Include="Insert.UInt32.1.cs" />
+ <Compile Include="Insert.Int64.1.cs" />
+ <Compile Include="Insert.UInt64.1.cs" />
+ <Compile Include="Insert.Single.0.cs" />
+ <Compile Include="Insert.Byte.129.cs" />
+ <Compile Include="Insert.SByte.129.cs" />
+ <Compile Include="Insert.Int32.129.cs" />
+ <Compile Include="Insert.UInt32.129.cs" />
+ <Compile Include="Insert.Int64.129.cs" />
+ <Compile Include="Insert.UInt64.129.cs" />
+ <Compile Include="Insert.Single.217.cs" />
<Compile Include="Program.Sse41.cs" />
<Compile Include="..\Shared\BooleanUnOpTest_DataTable.cs" />
<Compile Include="..\Shared\BooleanBinOpTest_DataTable.cs" />
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_ro.csproj
index 74dcfa091e..de6d56ed7e 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_ro.csproj
+++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse41/Sse41_ro.csproj
@@ -119,6 +119,34 @@
<Compile Include="TestZ.UInt16.cs" />
<Compile Include="TestZ.UInt32.cs" />
<Compile Include="TestZ.UInt64.cs" />
+ <Compile Include="Extract.Byte.1.cs" />
+ <Compile Include="Extract.SByte.1.cs" />
+ <Compile Include="Extract.Int32.1.cs" />
+ <Compile Include="Extract.UInt32.1.cs" />
+ <Compile Include="Extract.Int64.1.cs" />
+ <Compile Include="Extract.UInt64.1.cs" />
+ <Compile Include="Extract.Single.1.cs" />
+ <Compile Include="Extract.Byte.129.cs" />
+ <Compile Include="Extract.SByte.129.cs" />
+ <Compile Include="Extract.Int32.129.cs" />
+ <Compile Include="Extract.UInt32.129.cs" />
+ <Compile Include="Extract.Int64.129.cs" />
+ <Compile Include="Extract.UInt64.129.cs" />
+ <Compile Include="Extract.Single.129.cs" />
+ <Compile Include="Insert.Byte.1.cs" />
+ <Compile Include="Insert.SByte.1.cs" />
+ <Compile Include="Insert.Int32.1.cs" />
+ <Compile Include="Insert.UInt32.1.cs" />
+ <Compile Include="Insert.Int64.1.cs" />
+ <Compile Include="Insert.UInt64.1.cs" />
+ <Compile Include="Insert.Single.0.cs" />
+ <Compile Include="Insert.Byte.129.cs" />
+ <Compile Include="Insert.SByte.129.cs" />
+ <Compile Include="Insert.Int32.129.cs" />
+ <Compile Include="Insert.UInt32.129.cs" />
+ <Compile Include="Insert.Int64.129.cs" />
+ <Compile Include="Insert.UInt64.129.cs" />
+ <Compile Include="Insert.Single.217.cs" />
<Compile Include="Program.Sse41.cs" />
<Compile Include="..\Shared\BooleanUnOpTest_DataTable.cs" />
<Compile Include="..\Shared\BooleanBinOpTest_DataTable.cs" />