diff --git a/eng/native.wasm.targets b/eng/native.wasm.targets index c72c24ff6df2d1..7e6754795c8717 100644 --- a/eng/native.wasm.targets +++ b/eng/native.wasm.targets @@ -56,12 +56,14 @@ false false false + false <_CoreCLRPropertyThatTriggersRelinking Include="InvariantGlobalization" RuntimePackValue="$(BrowserHostInvariantGlobalization)" /> <_CoreCLRPropertyThatTriggersRelinking Include="InvariantTimezone" RuntimePackValue="$(BrowserHostInvariantTimezone)" /> <_CoreCLRPropertyThatTriggersRelinking Include="EnableDiagnostics" RuntimePackValue="$(BrowserHostEnableDiagnostics)" /> + <_CoreCLRPropertyThatTriggersRelinking Include="WasmEnableRelaxedSimd" RuntimePackValue="$(BrowserHostEnableRelaxedSimd)" /> <_CoreCLRPropertyThatTriggersRelinking Include="WasmInitialHeapSize" RuntimePackValue="$(BrowserHostInitialHeapSize)" /> <_CoreCLRPropertyThatTriggersRelinking Include="EmccMaximumHeapSize" RuntimePackValue="$(BrowserHostMaximumHeapSize)" /> <_CoreCLRPropertyThatTriggersRelinking Include="EmccStackSize" RuntimePackValue="$(BrowserHostStackSize)" /> diff --git a/eng/pipelines/coreclr/hardware-intrinsics-wasm.yml b/eng/pipelines/coreclr/hardware-intrinsics-wasm.yml index 4db8cafecc02a9..c21c1649ad19ba 100644 --- a/eng/pipelines/coreclr/hardware-intrinsics-wasm.yml +++ b/eng/pipelines/coreclr/hardware-intrinsics-wasm.yml @@ -28,4 +28,4 @@ extends: parameters: platforms: - browser_wasm - testBuildArgs: '/p:EnableWasmHWIntrinsicsTests=true -tree:JIT/HardwareIntrinsics/Wasm' + testBuildArgs: '/p:EnableWasmHWIntrinsicsTests=true /p:WasmEnableRelaxedSimd=true -tree:JIT/HardwareIntrinsics/Wasm' diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 74c90c04774dc9..4d43fb63e1bbd3 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -1255,7 +1255,7 @@ extends: runOnlyOnChromeVersionUpdate: true shouldRunSmokeOnly: 'true' nameSuffix: _SmokeMac - extraBuildArgs: /p:AotHostArchitecture=arm64 /p:AotHostOS=$(_hostedOS) + extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) useHelixMonitor: ${{ variables.enableHelixJobMonitor }} scenarios: - WasmTestOnChrome diff --git a/eng/testing/BrowserVersions.props b/eng/testing/BrowserVersions.props index 6b37f314e7d5a5..07fbfadb0a4c94 100644 --- a/eng/testing/BrowserVersions.props +++ b/eng/testing/BrowserVersions.props @@ -12,9 +12,9 @@ 1689415 https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/1689481 15.4.80 - 140.11.0esr + 155.0.1 0.37.0 - 140.11.0esr + 155.0.1 0.37.0 \ No newline at end of file diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets index 63a30b0f8a6741..cd5d65bcf48071 100644 --- a/eng/testing/tests.wasm.targets +++ b/eng/testing/tests.wasm.targets @@ -89,12 +89,16 @@ --> <_WasmIntrinsicsSubstitutions Condition="'$(WasmEnableSIMD)' != 'false'">WasmIntrinsics <_WasmIntrinsicsSubstitutions Condition="'$(WasmEnableSIMD)' == 'false'">NoWasmIntrinsics + <_WasmRelaxedSimdSubstitutions Condition="'$(WasmEnableSIMD)' != 'false' and '$(WasmEnableRelaxedSimd)' == 'true'">WasmRelaxedSimd + <_WasmRelaxedSimdSubstitutions Condition="'$(WasmEnableSIMD)' != 'false' and '$(WasmEnableRelaxedSimd)' != 'true'">NoWasmRelaxedSimd <_WasmIntrinsicsSubstitutions Condition="'$(RuntimeFlavor)' == 'CoreCLR' and '$(PublishReadyToRun)' != 'true'">NoWasmIntrinsics + <_WasmRelaxedSimdSubstitutions Condition="'$(RuntimeFlavor)' == 'CoreCLR' and '$(PublishReadyToRun)' != 'true'"> <_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --substitutions "$(BrowserProjectRoot)build\ILLink.Substitutions.$(_WasmIntrinsicsSubstitutions).xml" + <_ExtraTrimmerArgs Condition="'$(_WasmRelaxedSimdSubstitutions)' != ''">$(_ExtraTrimmerArgs) --substitutions "$(BrowserProjectRoot)build\ILLink.Substitutions.$(_WasmRelaxedSimdSubstitutions).xml" @@ -165,6 +169,7 @@ <_WasmPropertyNames Include="WasmBuildNative" /> <_WasmPropertyNames Include="WasmDebugLevel" /> <_WasmPropertyNames Include="WasmDedup" /> + <_WasmPropertyNames Include="WasmEnableRelaxedSimd" /> <_WasmPropertyNames Include="WasmLinkIcalls" /> <_WasmPropertyNames Include="WasmNativeStrip" /> <_WasmPropertyNames Include="WasmNativeDebugSymbols" /> diff --git a/src/coreclr/inc/corinfoinstructionset.h b/src/coreclr/inc/corinfoinstructionset.h index 2f347572ee34d4..2d43c6cb2d925f 100644 --- a/src/coreclr/inc/corinfoinstructionset.h +++ b/src/coreclr/inc/corinfoinstructionset.h @@ -70,6 +70,7 @@ enum CORINFO_InstructionSet InstructionSet_WasmBase=1, InstructionSet_PackedSimd=2, InstructionSet_Vector128=3, + InstructionSet_RelaxedSimd=4, #endif // TARGET_WASM #ifdef TARGET_AMD64 InstructionSet_X86Base=1, @@ -473,6 +474,8 @@ inline CORINFO_InstructionSetFlags EnsureInstructionSetFlagsAreValid(CORINFO_Ins #ifdef TARGET_WASM if (resultflags.HasInstructionSet(InstructionSet_Vector128) && !resultflags.HasInstructionSet(InstructionSet_PackedSimd)) resultflags.RemoveInstructionSet(InstructionSet_Vector128); + if (resultflags.HasInstructionSet(InstructionSet_RelaxedSimd) && !resultflags.HasInstructionSet(InstructionSet_PackedSimd)) + resultflags.RemoveInstructionSet(InstructionSet_RelaxedSimd); if (resultflags.HasInstructionSet(InstructionSet_PackedSimd) && !resultflags.HasInstructionSet(InstructionSet_WasmBase)) resultflags.RemoveInstructionSet(InstructionSet_PackedSimd); #endif // TARGET_WASM @@ -785,6 +788,8 @@ inline const char *InstructionSetToString(CORINFO_InstructionSet instructionSet) return "PackedSimd"; case InstructionSet_Vector128 : return "Vector128"; + case InstructionSet_RelaxedSimd : + return "RelaxedSimd"; #endif // TARGET_WASM #ifdef TARGET_AMD64 case InstructionSet_X86Base : @@ -993,6 +998,7 @@ inline CORINFO_InstructionSet InstructionSetFromR2RInstructionSet(ReadyToRunInst #ifdef TARGET_WASM case READYTORUN_INSTRUCTION_WasmBase: return InstructionSet_WasmBase; case READYTORUN_INSTRUCTION_PackedSimd: return InstructionSet_PackedSimd; + case READYTORUN_INSTRUCTION_RelaxedSimd: return InstructionSet_RelaxedSimd; #endif // TARGET_WASM #ifdef TARGET_AMD64 case READYTORUN_INSTRUCTION_X86Base: return InstructionSet_X86Base; diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 529831e7e5aada..aef310a48c8bda 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -37,11 +37,11 @@ #include -constexpr GUID JITEEVersionIdentifier = { /* d3368fe9-d21b-4c5c-9786-49f591047bf7 */ - 0xd3368fe9, - 0xd21b, - 0x4c5c, - {0x97, 0x86, 0x49, 0xf5, 0x91, 0x04, 0x7b, 0xf7} +constexpr GUID JITEEVersionIdentifier = { /* d663060e-9184-48cb-b7dc-c8afa4b33a82 */ + 0xd663060e, + 0x9184, + 0x48cb, + {0xb7, 0xdc, 0xc8, 0xaf, 0xa4, 0xb3, 0x3a, 0x82} }; #endif // JIT_EE_VERSIONING_GUID_H diff --git a/src/coreclr/inc/readytoruninstructionset.h b/src/coreclr/inc/readytoruninstructionset.h index d2851e91577f1e..4e1c644737d4ff 100644 --- a/src/coreclr/inc/readytoruninstructionset.h +++ b/src/coreclr/inc/readytoruninstructionset.h @@ -103,6 +103,7 @@ enum ReadyToRunInstructionSet READYTORUN_INSTRUCTION_Cssc=93, READYTORUN_INSTRUCTION_Zicond=94, READYTORUN_INSTRUCTION_Fp16=95, + READYTORUN_INSTRUCTION_RelaxedSimd=96, }; diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index d84f1dfa732107..9d29971768efa5 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -1019,6 +1019,7 @@ static const HWIntrinsicIsaRange hwintrinsicIsaRangeArray[] = { { FIRST_NI_WasmBase, LAST_NI_WasmBase }, // WasmBase { FIRST_NI_PackedSimd, LAST_NI_PackedSimd }, // PackedSimd { FIRST_NI_Vector, LAST_NI_Vector }, // Vector128 + { FIRST_NI_RelaxedSimd, LAST_NI_RelaxedSimd }, // RelaxedSimd #else #error Unsupported platform #endif diff --git a/src/coreclr/jit/hwintrinsiclistwasm.h b/src/coreclr/jit/hwintrinsiclistwasm.h index c639f343656889..c07b42396f6105 100644 --- a/src/coreclr/jit/hwintrinsiclistwasm.h +++ b/src/coreclr/jit/hwintrinsiclistwasm.h @@ -82,6 +82,21 @@ HARDWARE_INTRINSIC(PackedSimd, ZeroExtendWideningLower, HARDWARE_INTRINSIC(PackedSimd, ZeroExtendWideningUpper, 16, 1, INS_i16x8_extend_high_u_i8x16, INS_i16x8_extend_high_u_i8x16, INS_i32x4_extend_high_u_i16x8, INS_i32x4_extend_high_u_i16x8, INS_i64x2_extend_high_u_i32x4, INS_i64x2_extend_high_u_i32x4, INS_invalid, INS_invalid, INS_invalid, INS_invalid, -1, -1, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) #define LAST_NI_PackedSimd NI_PackedSimd_ZeroExtendWideningUpper +// RelaxedSimd Intrinsics +#define FIRST_NI_RelaxedSimd NI_RelaxedSimd_ConvertToInt32Native +HARDWARE_INTRINSIC(RelaxedSimd, ConvertToInt32Native, 16, 1, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_i32x4_relaxed_trunc_f32x4_s, INS_i32x4_relaxed_trunc_f64x2_s_zero, -1, -1, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(RelaxedSimd, ConvertToUInt32Native, 16, 1, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_i32x4_relaxed_trunc_f32x4_u, INS_i32x4_relaxed_trunc_f64x2_u_zero, -1, -1, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(RelaxedSimd, DotProductAddNative, 16, 3, INS_i32x4_relaxed_dot_i8x16_i7x16_add_s, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, -1, -1, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(RelaxedSimd, DotProductNative, 16, 2, INS_i16x8_relaxed_dot_i8x16_i7x16_s, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, -1, -1, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(RelaxedSimd, LaneSelectNative, 16, 3, INS_i8x16_relaxed_laneselect, INS_i8x16_relaxed_laneselect, INS_i16x8_relaxed_laneselect, INS_i16x8_relaxed_laneselect, INS_i32x4_relaxed_laneselect, INS_i32x4_relaxed_laneselect, INS_i64x2_relaxed_laneselect, INS_i64x2_relaxed_laneselect, INS_invalid, INS_invalid, -1, -1, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(RelaxedSimd, MaxNative, 16, 2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_f32x4_relaxed_max, INS_f64x2_relaxed_max, -1, -1, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(RelaxedSimd, MinNative, 16, 2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_f32x4_relaxed_min, INS_f64x2_relaxed_min, -1, -1, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(RelaxedSimd, MultiplyAddEstimate, 16, 3, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_f32x4_relaxed_madd, INS_f64x2_relaxed_madd, -1, -1, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(RelaxedSimd, MultiplyAddNegatedEstimate, 16, 3, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_f32x4_relaxed_nmadd, INS_f64x2_relaxed_nmadd, -1, -1, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(RelaxedSimd, MultiplyRoundedQ15Native, 16, 2, INS_invalid, INS_invalid, INS_i16x8_relaxed_q15mulr_s, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, -1, -1, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(RelaxedSimd, SwizzleNative, 16, 2, INS_i8x16_relaxed_swizzle, INS_i8x16_relaxed_swizzle, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, -1, -1, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +#define LAST_NI_RelaxedSimd NI_RelaxedSimd_SwizzleNative + // WasmBase Intrinsics // These scalar intrinsics are special-imported (see hwintrinsicwasm.cpp) and always rewritten into the // existing NI_PRIMITIVE_*ZeroCount GT_INTRINSIC nodes (which codegen already emits as wasm clz/ctz), so diff --git a/src/coreclr/jit/hwintrinsicwasm.cpp b/src/coreclr/jit/hwintrinsicwasm.cpp index 859f0390554eaa..13c2bd6c2f2d75 100644 --- a/src/coreclr/jit/hwintrinsicwasm.cpp +++ b/src/coreclr/jit/hwintrinsicwasm.cpp @@ -25,6 +25,10 @@ CORINFO_InstructionSet Compiler::lookupInstructionSet(const char* className) { return InstructionSet_PackedSimd; } + else if (strcmp(className, "RelaxedSimd") == 0) + { + return InstructionSet_RelaxedSimd; + } else if ((strcmp(className, "Vector128") == 0) || (strcmp(className, "Vector128`1") == 0)) { return InstructionSet_Vector128; diff --git a/src/coreclr/jit/instrswasm.h b/src/coreclr/jit/instrswasm.h index 095a1d997b497a..fc6cdd0be83b73 100644 --- a/src/coreclr/jit/instrswasm.h +++ b/src/coreclr/jit/instrswasm.h @@ -527,6 +527,28 @@ INST2(i32x4_trunc_sat_u_f64x2_zero, "i32x4.trunc_sat_u_f64x2_zero", 0, IF_OP INST2(f64x2_convert_low_s_i32x4, "f64x2.convert_low_s_i32x4", 0, IF_OPCODE, 0xFD, 254) INST2(f64x2_convert_low_u_i32x4, "f64x2.convert_low_u_i32x4", 0, IF_OPCODE, 0xFD, 255) +// Relaxed SIMD operations +INST2(i8x16_relaxed_swizzle, "i8x16.relaxed_swizzle", 0, IF_OPCODE, 0xFD, 0x100) +INST2(i32x4_relaxed_trunc_f32x4_s, "i32x4.relaxed_trunc_f32x4_s", 0, IF_OPCODE, 0xFD, 0x101) +INST2(i32x4_relaxed_trunc_f32x4_u, "i32x4.relaxed_trunc_f32x4_u", 0, IF_OPCODE, 0xFD, 0x102) +INST2(i32x4_relaxed_trunc_f64x2_s_zero, "i32x4.relaxed_trunc_f64x2_s_zero", 0, IF_OPCODE, 0xFD, 0x103) +INST2(i32x4_relaxed_trunc_f64x2_u_zero, "i32x4.relaxed_trunc_f64x2_u_zero", 0, IF_OPCODE, 0xFD, 0x104) +INST2(f32x4_relaxed_madd, "f32x4.relaxed_madd", 0, IF_OPCODE, 0xFD, 0x105) +INST2(f32x4_relaxed_nmadd, "f32x4.relaxed_nmadd", 0, IF_OPCODE, 0xFD, 0x106) +INST2(f64x2_relaxed_madd, "f64x2.relaxed_madd", 0, IF_OPCODE, 0xFD, 0x107) +INST2(f64x2_relaxed_nmadd, "f64x2.relaxed_nmadd", 0, IF_OPCODE, 0xFD, 0x108) +INST2(i8x16_relaxed_laneselect, "i8x16.relaxed_laneselect", 0, IF_OPCODE, 0xFD, 0x109) +INST2(i16x8_relaxed_laneselect, "i16x8.relaxed_laneselect", 0, IF_OPCODE, 0xFD, 0x10A) +INST2(i32x4_relaxed_laneselect, "i32x4.relaxed_laneselect", 0, IF_OPCODE, 0xFD, 0x10B) +INST2(i64x2_relaxed_laneselect, "i64x2.relaxed_laneselect", 0, IF_OPCODE, 0xFD, 0x10C) +INST2(f32x4_relaxed_min, "f32x4.relaxed_min", 0, IF_OPCODE, 0xFD, 0x10D) +INST2(f32x4_relaxed_max, "f32x4.relaxed_max", 0, IF_OPCODE, 0xFD, 0x10E) +INST2(f64x2_relaxed_min, "f64x2.relaxed_min", 0, IF_OPCODE, 0xFD, 0x10F) +INST2(f64x2_relaxed_max, "f64x2.relaxed_max", 0, IF_OPCODE, 0xFD, 0x110) +INST2(i16x8_relaxed_q15mulr_s, "i16x8.relaxed_q15mulr_s", 0, IF_OPCODE, 0xFD, 0x111) +INST2(i16x8_relaxed_dot_i8x16_i7x16_s, "i16x8.relaxed_dot_i8x16_i7x16_s", 0, IF_OPCODE, 0xFD, 0x112) +INST2(i32x4_relaxed_dot_i8x16_i7x16_add_s, "i32x4.relaxed_dot_i8x16_i7x16_add_s", 0, IF_OPCODE, 0xFD, 0x113) + // clang-format on #undef INST diff --git a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs index 4c5574d6870c32..075243f63cf82e 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs @@ -106,5 +106,6 @@ public enum ReadyToRunInstructionSet Cssc = 93, Zicond = 94, Fp16 = 95, + RelaxedSimd = 96, } } diff --git a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSetHelper.cs b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSetHelper.cs index 632e3053189a72..0d9f42b7b29d4c 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSetHelper.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSetHelper.cs @@ -89,6 +89,7 @@ public static class ReadyToRunInstructionSetHelper case InstructionSet.Wasm32_WasmBase: return ReadyToRunInstructionSet.WasmBase; case InstructionSet.Wasm32_PackedSimd: return ReadyToRunInstructionSet.PackedSimd; case InstructionSet.Wasm32_Vector128: return null; + case InstructionSet.Wasm32_RelaxedSimd: return ReadyToRunInstructionSet.RelaxedSimd; default: throw new Exception("Unknown instruction set"); } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs b/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs index 870544e2156425..e2bb9d87c7fe66 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs @@ -66,6 +66,7 @@ public enum InstructionSet Wasm32_WasmBase = InstructionSet_Wasm32.WasmBase, Wasm32_PackedSimd = InstructionSet_Wasm32.PackedSimd, Wasm32_Vector128 = InstructionSet_Wasm32.Vector128, + Wasm32_RelaxedSimd = InstructionSet_Wasm32.RelaxedSimd, X64_X86Base = InstructionSet_X64.X86Base, X64_AVX = InstructionSet_X64.AVX, X64_AVX2 = InstructionSet_X64.AVX2, @@ -224,6 +225,7 @@ public enum InstructionSet_Wasm32 WasmBase = 1, PackedSimd = 2, Vector128 = 3, + RelaxedSimd = 4, } public enum InstructionSet_X64 @@ -620,6 +622,8 @@ public static InstructionSetFlags ExpandInstructionSetByImplicationHelper(Target case TargetArchitecture.Wasm32: if (resultflags.HasInstructionSet(InstructionSet.Wasm32_Vector128)) resultflags.AddInstructionSet(InstructionSet.Wasm32_PackedSimd); + if (resultflags.HasInstructionSet(InstructionSet.Wasm32_RelaxedSimd)) + resultflags.AddInstructionSet(InstructionSet.Wasm32_PackedSimd); if (resultflags.HasInstructionSet(InstructionSet.Wasm32_PackedSimd)) resultflags.AddInstructionSet(InstructionSet.Wasm32_WasmBase); break; @@ -823,6 +827,7 @@ public static InstructionSetFlags ExpandInstructionSetByImplicationHelper(Target return resultflags; } + // Expands unsupported instruction sets. If A implies B and B is unsupported, A is unsupported too. public void ExpandInstructionSetByReverseImplication(TargetArchitecture architecture) { this = ExpandInstructionSetByReverseImplicationHelper(architecture, this); @@ -931,6 +936,8 @@ private static InstructionSetFlags ExpandInstructionSetByReverseImplicationHelpe case TargetArchitecture.Wasm32: if (resultflags.HasInstructionSet(InstructionSet.Wasm32_PackedSimd)) resultflags.AddInstructionSet(InstructionSet.Wasm32_Vector128); + if (resultflags.HasInstructionSet(InstructionSet.Wasm32_PackedSimd)) + resultflags.AddInstructionSet(InstructionSet.Wasm32_RelaxedSimd); if (resultflags.HasInstructionSet(InstructionSet.Wasm32_WasmBase)) resultflags.AddInstructionSet(InstructionSet.Wasm32_PackedSimd); break; @@ -1194,6 +1201,7 @@ public static IEnumerable ArchitectureToValidInstructionSets yield return new InstructionSetInfo("base", "WasmBase", InstructionSet.Wasm32_WasmBase, true); yield return new InstructionSetInfo("simd128", "PackedSimd", InstructionSet.Wasm32_PackedSimd, true); yield return new InstructionSetInfo("Vector128", "", InstructionSet.Wasm32_Vector128, false); + yield return new InstructionSetInfo("relaxed-simd", "RelaxedSimd", InstructionSet.Wasm32_RelaxedSimd, true); break; case TargetArchitecture.X64: @@ -1663,6 +1671,9 @@ public static InstructionSet LookupPlatformIntrinsicInstructionSet(TargetArchite case "PackedSimd": return InstructionSet.Wasm32_PackedSimd; + case "RelaxedSimd": + return InstructionSet.Wasm32_RelaxedSimd; + default: return InstructionSet.ILLEGAL; } @@ -2369,6 +2380,16 @@ public static IEnumerable LookupPlatformIntrinsicTypes(TypeSystemC } break; + case (InstructionSet.Wasm32_RelaxedSimd, TargetArchitecture.Wasm32): + { + var type = context.SystemModule.GetType("System.Runtime.Intrinsics.Wasm"u8, "RelaxedSimd"u8, false); + if (type != null) + { + yield return type; + } + } + break; + case (InstructionSet.X64_X86Base, TargetArchitecture.X64): case (InstructionSet.X64_X86Base_X64, TargetArchitecture.X64): { diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt index a70cd7d9991687..a8a04d44dec630 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt @@ -26,7 +26,7 @@ ; DO NOT CHANGE R2R NUMERIC VALUES OF THE EXISTING SETS. Changing R2R numeric values definitions would be R2R format breaking change. ; The ISA definitions should also be mapped to `hwintrinsicIsaRangeArray` in hwintrinsic.cpp. -; NEXT_AVAILABLE_R2R_BIT = 96 +; NEXT_AVAILABLE_R2R_BIT = 97 ; Definition of X86 instruction sets definearch ,X86 ,32Bit ,X64, X64, X86 @@ -323,7 +323,9 @@ definearch ,Wasm32 ,32Bit , , ,Wasm instructionset ,Wasm32 ,WasmBase , ,91 ,WasmBase ,base instructionset ,Wasm32 ,PackedSimd , ,92 ,PackedSimd ,simd128 instructionset ,Wasm32 , , , ,Vector128 , +instructionset ,Wasm32 ,RelaxedSimd , ,96 ,RelaxedSimd ,relaxed-simd vectorinstructionset ,Wasm32 ,Vector128 implication ,Wasm32 ,Vector128 ,PackedSimd +implication ,Wasm32 ,RelaxedSimd ,PackedSimd implication ,Wasm32 ,PackedSimd ,WasmBase \ No newline at end of file diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs index d15da9ddbff34c..d89ed8f17f39e6 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs @@ -636,6 +636,7 @@ public static InstructionSetFlags ExpandInstructionSetByImplicationHelper(Target return resultflags; } + // Expands unsupported instruction sets. If A implies B and B is unsupported, A is unsupported too. public void ExpandInstructionSetByReverseImplication(TargetArchitecture architecture) { this = ExpandInstructionSetByReverseImplicationHelper(architecture, this); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs index 8a1c6dd1e5a582..f1b372bbadea31 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs @@ -352,18 +352,6 @@ static void Validate(ReadyToRunReader reader) static string Format(IReadOnlyList valTypes) => $"[{string.Join(",", valTypes.Select(b => $"0x{b:X2}"))}]"; } - - static WebcilImageReader.WasmFunctionInfo ResolveWasmBody( - ReadyToRunReader reader, WebcilImageReader webcilReader, ReadyToRunMethod method) - { - uint tableIndex = checked(reader.WasmMinFunctionTableIndex + (uint)method.EntryPointRuntimeFunctionId); - int functionIndex = webcilReader.GetFunctionIndexFromTableIndex(tableIndex); - Assert.True(functionIndex >= 0, $"Could not resolve wasm table index {tableIndex} to a function body."); - - WebcilImageReader.WasmFunctionInfo? body = webcilReader.GetWasmFunctionBody(functionIndex); - Assert.True(body is not null, $"Wasm function body {functionIndex} was not found."); - return body.Value; - } } [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsWasmTarget))] @@ -411,6 +399,18 @@ static void Validate(ReadyToRunReader reader) } } + private static WebcilImageReader.WasmFunctionInfo ResolveWasmBody( + ReadyToRunReader reader, WebcilImageReader webcilReader, ReadyToRunMethod method) + { + uint tableIndex = checked(reader.WasmMinFunctionTableIndex + (uint)method.EntryPointRuntimeFunctionId); + int functionIndex = webcilReader.GetFunctionIndexFromTableIndex(tableIndex); + Assert.True(functionIndex >= 0, $"Could not resolve wasm table index {tableIndex} to a function body."); + + WebcilImageReader.WasmFunctionInfo? body = webcilReader.GetWasmFunctionBody(functionIndex); + Assert.True(body is not null, $"Wasm function body {functionIndex} was not found."); + return body.Value; + } + [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))] public void RuntimeFunctionsSectionSizeExcludesSentinel() { diff --git a/src/coreclr/tools/r2rdump/WasmDisassembler.cs b/src/coreclr/tools/r2rdump/WasmDisassembler.cs index 268f6632ea43d8..950c867f45de38 100644 --- a/src/coreclr/tools/r2rdump/WasmDisassembler.cs +++ b/src/coreclr/tools/r2rdump/WasmDisassembler.cs @@ -915,6 +915,28 @@ private string DecodeFDPrefixed() case 254: return "f32x4.demote_f64x2_zero"; case 255: return "f64x2.promote_low_f32x4"; + // Relaxed SIMD instructions + case 0x100: return "i8x16.relaxed_swizzle"; + case 0x101: return "i32x4.relaxed_trunc_f32x4_s"; + case 0x102: return "i32x4.relaxed_trunc_f32x4_u"; + case 0x103: return "i32x4.relaxed_trunc_f64x2_s_zero"; + case 0x104: return "i32x4.relaxed_trunc_f64x2_u_zero"; + case 0x105: return "f32x4.relaxed_madd"; + case 0x106: return "f32x4.relaxed_nmadd"; + case 0x107: return "f64x2.relaxed_madd"; + case 0x108: return "f64x2.relaxed_nmadd"; + case 0x109: return "i8x16.relaxed_laneselect"; + case 0x10A: return "i16x8.relaxed_laneselect"; + case 0x10B: return "i32x4.relaxed_laneselect"; + case 0x10C: return "i64x2.relaxed_laneselect"; + case 0x10D: return "f32x4.relaxed_min"; + case 0x10E: return "f32x4.relaxed_max"; + case 0x10F: return "f64x2.relaxed_min"; + case 0x110: return "f64x2.relaxed_max"; + case 0x111: return "i16x8.relaxed_q15mulr_s"; + case 0x112: return "i16x8.relaxed_dot_i8x16_i7x16_s"; + case 0x113: return "i32x4.relaxed_dot_i8x16_i7x16_add_s"; + default: return $""; } diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index dcfdcfcf0d78e0..ce035194763e58 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -1463,6 +1463,15 @@ extern "C" DWORD64 __stdcall GetDataCacheZeroIDReg(); extern "C" uint64_t GetSveLengthFromOS(); #endif +#ifdef TARGET_WASM +static bool s_wasmRelaxedSimdSupported; + +extern "C" void coreclr_wasm_set_relaxed_simd_supported() +{ + s_wasmRelaxedSimdSupported = true; +} +#endif + void EEJitManager::SetCpuInfo() { LIMITED_METHOD_CONTRACT; @@ -1507,6 +1516,10 @@ void EEJitManager::SetCpuInfo() #if defined(TARGET_WASM) CPUCompileFlags.Set(InstructionSet_WasmBase); CPUCompileFlags.Set(InstructionSet_PackedSimd); + if (s_wasmRelaxedSimdSupported) + { + CPUCompileFlags.Set(InstructionSet_RelaxedSimd); + } #endif #if defined(TARGET_X86) || defined(TARGET_AMD64) diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index 5c36a463c5e5a6..54aa41f3adfed2 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -229,6 +229,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 867e3a6fdca01f..5bf9cc9939191d 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -2919,10 +2919,12 @@ + + diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.cs index 0ffe3d96f4fcc9..89e8687a746c77 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.cs @@ -15,7 +15,7 @@ public abstract class PackedSimd /// Gets a value that indicates whether the APIs in this class are supported. /// if the APIs are supported; otherwise, . /// A value of indicates that the APIs will throw . - public static bool IsSupported { [Intrinsic] get { return IsSupported; } } + public static bool IsSupported { get { return IsSupported; } } // Constructing SIMD Values @@ -26,73 +26,61 @@ public abstract class PackedSimd /// v128_t wasm_i8x16_splat (int8_t a) /// i8x16.splat : [i32] -> [v128] /// - [Intrinsic] public static Vector128 Splat(sbyte value) => Splat(value); /// /// v128_t wasm_u8x16_splat (uint8_t a) /// i8x16.splat : [i32] -> [v128] /// - [Intrinsic] public static Vector128 Splat(byte value) => Splat(value); /// /// v128_t wasm_i16x8_splat (int16_t a) /// i16x8.splat : [i32] -> [v128] /// - [Intrinsic] public static Vector128 Splat(short value) => Splat(value); /// /// v128_t wasm_u16x8_splat (uint16_t a) /// i16x8.splat : [i32] -> [v128] /// - [Intrinsic] public static Vector128 Splat(ushort value) => Splat(value); /// /// v128_t wasm_i32x4_splat (int32_t a) /// i32x4.splat : [i32] -> [v128] /// - [Intrinsic] public static Vector128 Splat(int value) => Splat(value); /// /// v128_t wasm_u32x4_splat (uint32_t a) /// i32x4.splat : [i32] -> [v128] /// - [Intrinsic] public static Vector128 Splat(uint value) => Splat(value); /// /// v128_t wasm_i64x2_splat (int64_t a) /// i64x2.splat : [i64] -> [v128] /// - [Intrinsic] public static Vector128 Splat(long value) => Splat(value); /// /// v128_t wasm_u64x2_splat (uint64_t a) /// i64x2.splat : [i64] -> [v128] /// - [Intrinsic] public static Vector128 Splat(ulong value) => Splat(value); /// /// v128_t wasm_f32x4_splat (float a) /// f32x4.splat : [f32] -> [v128] /// - [Intrinsic] public static Vector128 Splat(float value) => Splat(value); /// /// v128_t wasm_f64x2_splat (double a) /// f64x2.splat : [f64] -> [v128] /// - [Intrinsic] public static Vector128 Splat(double value) => Splat(value); /// /// v128_t wasm_i32x4_splat (int32_t a) /// i32x4.splat : [i32] -> [v128] /// - [Intrinsic] public static Vector128 Splat(nint value) => Splat(value); /// /// v128_t wasm_u32x4_splat (uint32_t a) /// i32x4.splat : [i32] -> [v128] /// - [Intrinsic] public static Vector128 Splat(nuint value) => Splat(value); // Accessing lanes @@ -101,172 +89,144 @@ public abstract class PackedSimd /// int8_t wasm_i8x16_extract_lane (v128_t a, int i) /// i8x16.extract_lane_s laneidx : [v128] -> [i32] /// - [Intrinsic] public static int ExtractScalar(Vector128 value, [ConstantExpected(Max = (byte)(15))] byte index) => ExtractScalar(value, index); // takes ImmLaneIdx16 /// /// uint8_t wasm_u8x16_extract_lane (v128_t a, int i) /// i8x16.extract_lane_u laneidx : [v128] -> [i32] /// - [Intrinsic] public static uint ExtractScalar(Vector128 value, [ConstantExpected(Max = (byte)(15))] byte index) => ExtractScalar(value, index); // takes ImmLaneIdx16 /// /// int16_t wasm_i16x8_extract_lane (v128_t a, int i) /// i16x8.extract_lane_s laneidx : [v128] -> [i32] /// - [Intrinsic] public static int ExtractScalar(Vector128 value, [ConstantExpected(Max = (byte)(7))] byte index) => ExtractScalar(value, index); // takes ImmLaneIdx8 /// /// uint16_t wasm_u16x8_extract_lane (v128_t a, int i) /// i16x8.extract_lane_u laneidx : [v128] -> [i32] /// - [Intrinsic] public static uint ExtractScalar(Vector128 value, [ConstantExpected(Max = (byte)(7))] byte index) => ExtractScalar(value, index); // takes ImmLaneIdx8 /// /// int32_t wasm_i32x4_extract_lane (v128_t a, int i) /// i32x4.extract_lane laneidx : [v128] -> [i32] /// - [Intrinsic] public static int ExtractScalar(Vector128 value, [ConstantExpected(Max = (byte)(3))] byte index) => ExtractScalar(value, index); // takes ImmLaneIdx4 /// /// uint32_t wasm_u32x4_extract_lane (v128_t a, int i) /// i32x4.extract_lane laneidx : [v128] -> [i32] /// - [Intrinsic] public static uint ExtractScalar(Vector128 value, [ConstantExpected(Max = (byte)(3))] byte index) => ExtractScalar(value, index); // takes ImmLaneIdx4 /// /// int64_t wasm_i64x2_extract_lane (v128_t a, int i) /// i64x2.extract_lane laneidx : [v128] -> [i64] /// - [Intrinsic] public static long ExtractScalar(Vector128 value, [ConstantExpected(Max = (byte)(1))] byte index) => ExtractScalar(value, index); // takes ImmLaneIdx2 /// /// uint64_t wasm_u64x2_extract_lane (v128_t a, int i) /// i64x2.extract_lane laneidx : [v128] -> [i64] /// - [Intrinsic] public static ulong ExtractScalar(Vector128 value, [ConstantExpected(Max = (byte)(1))] byte index) => ExtractScalar(value, index); // takes ImmLaneIdx2 /// /// float wasm_f32x4_extract_lane (v128_t a, int i) /// f32x4.extract_lane laneidx : [v128] -> [f32] /// - [Intrinsic] public static float ExtractScalar(Vector128 value, [ConstantExpected(Max = (byte)(3))] byte index) => ExtractScalar(value, index); // takes ImmLaneIdx4 /// /// double wasm_f64x2_extract_lane (v128_t a, int i) /// f64x2.extract_lane laneidx : [v128] -> [f64] /// - [Intrinsic] public static double ExtractScalar(Vector128 value, [ConstantExpected(Max = (byte)(1))] byte index) => ExtractScalar(value, index); // takes ImmLaneIdx2 /// /// int32_t wasm_i32x4_extract_lane (v128_t a, int i) /// i32x4.extract_lane laneidx : [v128] -> [i32] /// - [Intrinsic] public static nint ExtractScalar(Vector128 value, [ConstantExpected(Max = (byte)(3))] byte index) => ExtractScalar(value, index); /// /// uint32_t wasm_u32x4_extract_lane (v128_t a, int i) /// i32x4.extract_lane laneidx : [v128] -> [i32] /// - [Intrinsic] public static nuint ExtractScalar(Vector128 value, [ConstantExpected(Max = (byte)(3))] byte index) => ExtractScalar(value, index); /// /// v128_t wasm_i8x16_replace_lane (v128_t a, int i, int8_t b) /// i8x16.replace_lane laneidx : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ReplaceScalar(Vector128 vector, [ConstantExpected(Max = (byte)(15))] byte imm, int value) => ReplaceScalar(vector, imm, value); // takes ImmLaneIdx16 /// /// v128_t wasm_u8x16_replace_lane (v128_t a, int i, uint8_t b) /// i8x16.replace_lane laneidx : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ReplaceScalar(Vector128 vector, [ConstantExpected(Max = (byte)(15))] byte imm, uint value) => ReplaceScalar(vector, imm, value); // takes ImmLaneIdx16 /// /// v128_t wasm_i16x8_replace_lane (v128_t a, int i, int16_t b) /// i16x8.replace_lane laneidx : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ReplaceScalar(Vector128 vector, [ConstantExpected(Max = (byte)(7))] byte imm, int value) => ReplaceScalar(vector, imm, value); // takes ImmLaneIdx8 /// /// v128_t wasm_u16x8_replace_lane (v128_t a, int i, uint16_t b) /// i16x8.replace_lane laneidx : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ReplaceScalar(Vector128 vector, [ConstantExpected(Max = (byte)(7))] byte imm, uint value) => ReplaceScalar(vector, imm, value); // takes ImmLaneIdx8 /// /// v128_t wasm_i32x4_replace_lane (v128_t a, int i, int32_t b) /// i32x4.replace_lane laneidx : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ReplaceScalar(Vector128 vector, [ConstantExpected(Max = (byte)(3))] byte imm, int value) => ReplaceScalar(vector, imm, value); // takes ImmLaneIdx4 /// /// v128_t wasm_u32x4_replace_lane (v128_t a, int i, uint32_t b) /// i32x4.replace_lane laneidx : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ReplaceScalar(Vector128 vector, [ConstantExpected(Max = (byte)(3))] byte imm, uint value) => ReplaceScalar(vector, imm, value); // takes ImmLaneIdx4 /// /// v128_t wasm_i64x2_replace_lane (v128_t a, int i, int64_t b) /// i64x2.replace_lane laneidx : [v128 i64] -> [v128] /// - [Intrinsic] public static Vector128 ReplaceScalar(Vector128 vector, [ConstantExpected(Max = (byte)(1))] byte imm, long value) => ReplaceScalar(vector, imm, value); // takes ImmLaneIdx2 /// /// v128_t wasm_u64x2_replace_lane (v128_t a, int i, uint64_t b) /// i64x2.replace_lane laneidx : [v128 i64] -> [v128] /// - [Intrinsic] public static Vector128 ReplaceScalar(Vector128 vector, [ConstantExpected(Max = (byte)(1))] byte imm, ulong value) => ReplaceScalar(vector, imm, value); // takes ImmLaneIdx2 /// /// v128_t wasm_f32x4_replace_lane (v128_t a, int i, float b) /// f32x4.replace_lane laneidx : [v128 f32] -> [v128] /// - [Intrinsic] public static Vector128 ReplaceScalar(Vector128 vector, [ConstantExpected(Max = (byte)(3))] byte imm, float value) => ReplaceScalar(vector, imm, value); // takes ImmLaneIdx4 /// /// v128_t wasm_f64x2_replace_lane (v128_t a, int i, double b) /// f64x2.replace_lane laneidx : [v128 f64] -> [v128] /// - [Intrinsic] public static Vector128 ReplaceScalar(Vector128 vector, [ConstantExpected(Max = (byte)(1))] byte imm, double value) => ReplaceScalar(vector, imm, value); // takes ImmLaneIdx2 /// /// v128_t wasm_i32x4_replace_lane (v128_t a, int i, int32_t b) /// i32x4.replace_lane laneidx : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ReplaceScalar(Vector128 vector, [ConstantExpected(Max = (byte)(3))] byte imm, nint value) => ReplaceScalar(vector, imm, value); /// /// v128_t wasm_u32x4_replace_lane (v128_t a, int i, uint32_t b) /// i32x4.replace_lane laneidx : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ReplaceScalar(Vector128 vector, [ConstantExpected(Max = (byte)(3))] byte imm, nuint value) => ReplaceScalar(vector, imm, value); /// /// v128_t wasm_i8x16_shuffle (v128_t a, v128_t b, int c0, int c1, int c2, int c3, int c4, int c5, int c6, int c7, int c8, int c9, int c10, int c11, int c12, int c13, int c14, int c15) /// i8x16.shuffle laneidx^16 : [v128 v128] -> [v128] /// - [Intrinsic] internal static Vector128 Shuffle(Vector128 lower, Vector128 upper, Vector128 indices) => Shuffle(lower, upper, indices); /// /// v128_t wasm_i8x16_shuffle (v128_t a, v128_t b, int c0, int c1, int c2, int c3, int c4, int c5, int c6, int c7, int c8, int c9, int c10, int c11, int c12, int c13, int c14, int c15) /// i8x16.shuffle laneidx^16 : [v128 v128] -> [v128] /// - [Intrinsic] internal static Vector128 Shuffle(Vector128 lower, Vector128 upper, Vector128 indices) => Shuffle(lower, upper, indices); /// /// v128_t wasm_i8x16_swizzle (v128_t a, v128_t b) /// i8x16.swizzle : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Swizzle(Vector128 vector, Vector128 indices) => Swizzle(vector, indices); /// /// v128_t wasm_i8x16_swizzle (v128_t a, v128_t b) /// i8x16.swizzle : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Swizzle(Vector128 vector, Vector128 indices) => Swizzle(vector, indices); // Integer arithmetic @@ -275,239 +235,200 @@ public abstract class PackedSimd /// v128_t wasm_i8x16_add (v128_t a, v128_t b) /// i8x16.add : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Add(Vector128 left, Vector128 right) => Add(left, right); /// /// v128_t wasm_i8x16_add (v128_t a, v128_t b) /// i8x16.add : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Add(Vector128 left, Vector128 right) => Add(left, right); /// /// v128_t wasm_i16x8_add (v128_t a, v128_t b) /// i16x8.add : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Add(Vector128 left, Vector128 right) => Add(left, right); /// /// v128_t wasm_i16x8_add (v128_t a, v128_t b) /// i16x8.add : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Add(Vector128 left, Vector128 right) => Add(left, right); /// /// v128_t wasm_i32x4_add (v128_t a, v128_t b) /// i32x4.add : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Add(Vector128 left, Vector128 right) => Add(left, right); /// /// v128_t wasm_i32x4_add (v128_t a, v128_t b) /// i32x4.add : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Add(Vector128 left, Vector128 right) => Add(left, right); /// /// v128_t wasm_i64x2_add (v128_t a, v128_t b) /// i64x2.add : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Add(Vector128 left, Vector128 right) => Add(left, right); /// /// v128_t wasm_i64x2_add (v128_t a, v128_t b) /// i64x2.add : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Add(Vector128 left, Vector128 right) => Add(left, right); /// /// v128_t wasm_i32x4_add (v128_t a, v128_t b) /// i32x4.add : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Add(Vector128 left, Vector128 right) => Add(left, right); /// /// v128_t wasm_i32x4_add (v128_t a, v128_t b) /// i32x4.add : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Add(Vector128 left, Vector128 right) => Add(left, right); /// /// v128_t wasm_i8x16_sub (v128_t a, v128_t b) /// i8x16.sub : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Subtract(Vector128 left, Vector128 right) => Subtract(left, right); /// /// v128_t wasm_i8x16_sub (v128_t a, v128_t b) /// i8x16.sub : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Subtract(Vector128 left, Vector128 right) => Subtract(left, right); /// /// v128_t wasm_i16x8_sub (v128_t a, v128_t b) /// i16x8.sub : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Subtract(Vector128 left, Vector128 right) => Subtract(left, right); /// /// v128_t wasm_i16x8_sub (v128_t a, v128_t b) /// i16x8.sub : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Subtract(Vector128 left, Vector128 right) => Subtract(left, right); /// /// v128_t wasm_i32x4_sub (v128_t a, v128_t b) /// i32x4.sub : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Subtract(Vector128 left, Vector128 right) => Subtract(left, right); /// /// v128_t wasm_i32x4_sub (v128_t a, v128_t b) /// i32x4.sub : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Subtract(Vector128 left, Vector128 right) => Subtract(left, right); /// /// v128_t wasm_i64x2_sub (v128_t a, v128_t b) /// i64x2.sub : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Subtract(Vector128 left, Vector128 right) => Subtract(left, right); /// /// v128_t wasm_i64x2_sub (v128_t a, v128_t b) /// i64x2.sub : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Subtract(Vector128 left, Vector128 right) => Subtract(left, right); /// /// v128_t wasm_i32x4_sub (v128_t a, v128_t b) /// i32x4.sub : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Subtract(Vector128 left, Vector128 right) => Subtract(left, right); /// /// v128_t wasm_i32x4_sub (v128_t a, v128_t b) /// i32x4.sub : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Subtract(Vector128 left, Vector128 right) => Subtract(left, right); /// /// v128_t wasm_i16x8_mul (v128_t a, v128_t b) /// i16x8.mul : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Multiply(Vector128 left, Vector128 right) => Multiply(left, right); /// /// v128_t wasm_i16x8_mul (v128_t a, v128_t b) /// i16x8.mul : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Multiply(Vector128 left, Vector128 right) => Multiply(left, right); /// /// v128_t wasm_i32x4_mul (v128_t a, v128_t b) /// i32x4.mul : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Multiply(Vector128 left, Vector128 right) => Multiply(left, right); /// /// v128_t wasm_i32x4_mul (v128_t a, v128_t b) /// i32x4.mul : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Multiply(Vector128 left, Vector128 right) => Multiply(left, right); /// /// v128_t wasm_i64x2_mul (v128_t a, v128_t b) /// i64x2.mul : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Multiply(Vector128 left, Vector128 right) => Multiply(left, right); /// /// v128_t wasm_i64x2_mul (v128_t a, v128_t b) /// i64x2.mul : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Multiply(Vector128 left, Vector128 right) => Multiply(left, right); /// /// v128_t wasm_i32x4_mul (v128_t a, v128_t b) /// i32x4.mul : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Multiply(Vector128 left, Vector128 right) => Multiply(left, right); /// /// v128_t wasm_i32x4_mul (v128_t a, v128_t b) /// i32x4.mul : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Multiply(Vector128 left, Vector128 right) => Multiply(left, right); /// /// v128_t wasm_i32x4_dot_i16x8 (v128_t a, v128_t b) /// i32x4.dot_i16x8_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Dot(Vector128 left, Vector128 right) => Dot(left, right); /// /// v128_t wasm_i8x16_neg (v128_t a) /// i8x16.neg : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Negate(Vector128 value) => Negate(value); /// /// v128_t wasm_i8x16_neg (v128_t a) /// i8x16.neg : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Negate(Vector128 value) => Negate(value); /// /// v128_t wasm_i16x8_neg (v128_t a) /// i16x8.neg : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Negate(Vector128 value) => Negate(value); /// /// v128_t wasm_i16x8_neg (v128_t a) /// i16x8.neg : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Negate(Vector128 value) => Negate(value); /// /// v128_t wasm_i32x4_neg (v128_t a) /// i32x4.neg : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Negate(Vector128 value) => Negate(value); /// /// v128_t wasm_i32x4_neg (v128_t a) /// i32x4.neg : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Negate(Vector128 value) => Negate(value); /// /// v128_t wasm_i64x2_neg (v128_t a) /// i64x2.neg : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Negate(Vector128 value) => Negate(value); /// /// v128_t wasm_i64x2_neg (v128_t a) /// i64x2.neg : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Negate(Vector128 value) => Negate(value); /// /// v128_t wasm_i32x4_neg (v128_t a) /// i32x4.neg : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Negate(Vector128 value) => Negate(value); /// /// v128_t wasm_i32x4_neg (v128_t a) /// i32x4.neg : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Negate(Vector128 value) => Negate(value); // Extended integer arithmetic @@ -516,99 +437,83 @@ public abstract class PackedSimd /// v128_t wasm_i16x8_extmul_low_i8x16 (v128_t a, v128_t b) /// i16x8.extmul_low_i8x16_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) => MultiplyWideningLower(left, right); /// /// v128_t wasm_u16x8_extmul_low_u8x16 (v128_t a, v128_t b) /// i16x8.extmul_low_i8x16_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) => MultiplyWideningLower(left, right); /// /// v128_t wasm_i32x4_extmul_low_i16x8 (v128_t a, v128_t b) /// i32x4.extmul_low_i16x8_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) => MultiplyWideningLower(left, right); /// /// v128_t wasm_u32x4_extmul_low_u16x8 (v128_t a, v128_t b) /// i32x4.extmul_low_i16x8_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) => MultiplyWideningLower(left, right); /// /// v128_t wasm_i64x2_extmul_low_i32x4 (v128_t a, v128_t b) /// i64x2.extmul_low_i32x4_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) => MultiplyWideningLower(left, right); /// /// v128_t wasm_u64x2_extmul_low_u32x4 (v128_t a, v128_t b) /// i64x2.extmul_low_i32x4_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) => MultiplyWideningLower(left, right); /// /// v128_t wasm_i16x8_extmul_high_i8x16 (v128_t a, v128_t b) /// i16x8.extmul_high_i8x16_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) => MultiplyWideningUpper(left, right); /// /// v128_t wasm_u16x8_extmul_high_u8x16 (v128_t a, v128_t b) /// i16x8.extmul_high_i8x16_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) => MultiplyWideningUpper(left, right); /// /// v128_t wasm_i32x4_extmul_high_i16x8 (v128_t a, v128_t b) /// i32x4.extmul_high_i16x8_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) => MultiplyWideningUpper(left, right); /// /// v128_t wasm_u32x4_extmul_high_u16x8 (v128_t a, v128_t b) /// i32x4.extmul_high_i16x8_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) => MultiplyWideningUpper(left, right); /// /// v128_t wasm_i64x2_extmul_high_i32x4 (v128_t a, v128_t b) /// i64x2.extmul_high_i32x4_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) => MultiplyWideningUpper(left, right); /// /// v128_t wasm_u64x2_extmul_high_u32x4 (v128_t a, v128_t b) /// i64x2.extmul_high_i32x4_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) => MultiplyWideningUpper(left, right); /// /// v128_t wasm_i16x8_extadd_pairwise_i8x16 (v128_t a) /// i16x8.extadd_pairwise_i8x16_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 AddPairwiseWidening(Vector128 value) => AddPairwiseWidening(value); /// /// v128_t wasm_u16x8_extadd_pairwise_u8x16 (v128_t a) /// i16x8.extadd_pairwise_i8x16_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 AddPairwiseWidening(Vector128 value) => AddPairwiseWidening(value); /// /// v128_t wasm_i32x4_extadd_pairwise_i16x8 (v128_t a) /// i32x4.extadd_pairwise_i16x8_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 AddPairwiseWidening(Vector128 value) => AddPairwiseWidening(value); /// /// v128_t wasm_u32x4_extadd_pairwise_u16x8 (v128_t a) /// i32x4.extadd_pairwise_i16x8_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 AddPairwiseWidening(Vector128 value) => AddPairwiseWidening(value); // Saturating integer arithmetic @@ -766,183 +671,153 @@ public abstract class PackedSimd /// v128_t wasm_i8x16_shl (v128_t a, uint32_t b) /// i8x16.shl : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftLeft(Vector128 value, int count) => ShiftLeft(value, count); /// /// v128_t wasm_i8x16_shl (v128_t a, uint32_t b) /// i8x16.shl : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftLeft(Vector128 value, int count) => ShiftLeft(value, count); /// /// v128_t wasm_i16x8_shl (v128_t a, uint32_t b) /// i16x8.shl : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftLeft(Vector128 value, int count) => ShiftLeft(value, count); /// /// v128_t wasm_i16x8_shl (v128_t a, uint32_t b) /// i16x8.shl : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftLeft(Vector128 value, int count) => ShiftLeft(value, count); /// /// v128_t wasm_i32x4_shl (v128_t a, uint32_t b) /// i32x4.shl : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftLeft(Vector128 value, int count) => ShiftLeft(value, count); /// /// v128_t wasm_i32x4_shl (v128_t a, uint32_t b) /// i32x4.shl : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftLeft(Vector128 value, int count) => ShiftLeft(value, count); /// /// v128_t wasm_i64x2_shl (v128_t a, uint32_t b) /// i64x2.shl : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftLeft(Vector128 value, int count) => ShiftLeft(value, count); /// /// v128_t wasm_i64x2_shl (v128_t a, uint32_t b) /// i64x2.shl : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftLeft(Vector128 value, int count) => ShiftLeft(value, count); /// /// v128_t wasm_i32x4_shl (v128_t a, uint32_t b) /// i32x4.shl : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftLeft(Vector128 value, int count) => ShiftLeft(value, count); /// /// v128_t wasm_i32x4_shl (v128_t a, uint32_t b) /// i32x4.shl : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftLeft(Vector128 value, int count) => ShiftLeft(value, count); /// /// v128_t wasm_i8x16_shr (v128_t a, uint32_t b) /// i8x16.shr_s : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightArithmetic(Vector128 value, int count) => ShiftRightArithmetic(value, count); /// /// v128_t wasm_i8x16_shr (v128_t a, uint32_t b) /// i8x16.shr_s : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightArithmetic(Vector128 value, int count) => ShiftRightArithmetic(value, count); /// /// v128_t wasm_i16x8_shr (v128_t a, uint32_t b) /// i16x8.shr_s : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightArithmetic(Vector128 value, int count) => ShiftRightArithmetic(value, count); /// /// v128_t wasm_i16x8_shr (v128_t a, uint32_t b) /// i16x8.shr_s : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightArithmetic(Vector128 value, int count) => ShiftRightArithmetic(value, count); /// /// v128_t wasm_i32x4_shr (v128_t a, uint32_t b) /// i32x4.shr_s : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightArithmetic(Vector128 value, int count) => ShiftRightArithmetic(value, count); /// /// v128_t wasm_i32x4_shr (v128_t a, uint32_t b) /// i32x4.shr_s : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightArithmetic(Vector128 value, int count) => ShiftRightArithmetic(value, count); /// /// v128_t wasm_i64x2_shr (v128_t a, uint32_t b) /// i64x2.shr_s : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightArithmetic(Vector128 value, int count) => ShiftRightArithmetic(value, count); /// /// v128_t wasm_i64x2_shr (v128_t a, uint32_t b) /// i64x2.shr_s : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightArithmetic(Vector128 value, int count) => ShiftRightArithmetic(value, count); /// /// v128_t wasm_i32x4_shr (v128_t a, uint32_t b) /// i32x4.shr_s : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightArithmetic(Vector128 value, int count) => ShiftRightArithmetic(value, count); /// /// v128_t wasm_i32x4_shr (v128_t a, uint32_t b) /// i32x4.shr_s : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightArithmetic(Vector128 value, int count) => ShiftRightArithmetic(value, count); /// /// v128_t wasm_u8x16_shr (v128_t a, uint32_t b) /// i8x16.shr_u : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightLogical(Vector128 value, int count) => ShiftRightLogical(value, count); /// /// v128_t wasm_u8x16_shr (v128_t a, uint32_t b) /// i8x16.shr_u : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightLogical(Vector128 value, int count) => ShiftRightLogical(value, count); /// /// v128_t wasm_u16x8_shr (v128_t a, uint32_t b) /// i16x8.shr_u : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightLogical(Vector128 value, int count) => ShiftRightLogical(value, count); /// /// v128_t wasm_u16x8_shr (v128_t a, uint32_t b) /// i16x8.shr_u : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightLogical(Vector128 value, int count) => ShiftRightLogical(value, count); /// /// v128_t wasm_u32x4_shr (v128_t a, uint32_t b) /// i32x4.shr_u : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightLogical(Vector128 value, int count) => ShiftRightLogical(value, count); /// /// v128_t wasm_u32x4_shr (v128_t a, uint32_t b) /// i32x4.shr_u : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightLogical(Vector128 value, int count) => ShiftRightLogical(value, count); /// /// v128_t wasm_u64x2_shr (v128_t a, uint32_t b) /// i64x2.shr_u : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightLogical(Vector128 value, int count) => ShiftRightLogical(value, count); /// /// v128_t wasm_u64x2_shr (v128_t a, uint32_t b) /// i64x2.shr_u : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightLogical(Vector128 value, int count) => ShiftRightLogical(value, count); /// /// v128_t wasm_u32x4_shr (v128_t a, uint32_t b) /// i32x4.shr_u : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightLogical(Vector128 value, int count) => ShiftRightLogical(value, count); /// /// v128_t wasm_u32x4_shr (v128_t a, uint32_t b) /// i32x4.shr_u : [v128 i32] -> [v128] /// - [Intrinsic] public static Vector128 ShiftRightLogical(Vector128 value, int count) => ShiftRightLogical(value, count); // Bitwise operations @@ -951,445 +826,372 @@ public abstract class PackedSimd /// v128_t wasm_v128_and (v128_t a, v128_t b) /// v128.and : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 And(Vector128 left, Vector128 right) => And(left, right); /// /// v128_t wasm_v128_and (v128_t a, v128_t b) /// v128.and : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 And(Vector128 left, Vector128 right) => And(left, right); /// /// v128_t wasm_v128_and (v128_t a, v128_t b) /// v128.and : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 And(Vector128 left, Vector128 right) => And(left, right); /// /// v128_t wasm_v128_and (v128_t a, v128_t b) /// v128.and : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 And(Vector128 left, Vector128 right) => And(left, right); /// /// v128_t wasm_v128_and (v128_t a, v128_t b) /// v128.and : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 And(Vector128 left, Vector128 right) => And(left, right); /// /// v128_t wasm_v128_and (v128_t a, v128_t b) /// v128.and : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 And(Vector128 left, Vector128 right) => And(left, right); /// /// v128_t wasm_v128_and (v128_t a, v128_t b) /// v128.and : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 And(Vector128 left, Vector128 right) => And(left, right); /// /// v128_t wasm_v128_and (v128_t a, v128_t b) /// v128.and : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 And(Vector128 left, Vector128 right) => And(left, right); /// /// v128_t wasm_v128_and (v128_t a, v128_t b) /// v128.and : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 And(Vector128 left, Vector128 right) => And(left, right); /// /// v128_t wasm_v128_and (v128_t a, v128_t b) /// v128.and : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 And(Vector128 left, Vector128 right) => And(left, right); /// /// v128_t wasm_v128_and (v128_t a, v128_t b) /// v128.and : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 And(Vector128 left, Vector128 right) => And(left, right); /// /// v128_t wasm_v128_and (v128_t a, v128_t b) /// v128.and : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 And(Vector128 left, Vector128 right) => And(left, right); /// /// v128_t wasm_v128_or (v128_t a, v128_t b) /// v128.or : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Or(Vector128 left, Vector128 right) => Or(left, right); /// /// v128_t wasm_v128_or (v128_t a, v128_t b) /// v128.or : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Or(Vector128 left, Vector128 right) => Or(left, right); /// /// v128_t wasm_v128_or (v128_t a, v128_t b) /// v128.or : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Or(Vector128 left, Vector128 right) => Or(left, right); /// /// v128_t wasm_v128_or (v128_t a, v128_t b) /// v128.or : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Or(Vector128 left, Vector128 right) => Or(left, right); /// /// v128_t wasm_v128_or (v128_t a, v128_t b) /// v128.or : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Or(Vector128 left, Vector128 right) => Or(left, right); /// /// v128_t wasm_v128_or (v128_t a, v128_t b) /// v128.or : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Or(Vector128 left, Vector128 right) => Or(left, right); /// /// v128_t wasm_v128_or (v128_t a, v128_t b) /// v128.or : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Or(Vector128 left, Vector128 right) => Or(left, right); /// /// v128_t wasm_v128_or (v128_t a, v128_t b) /// v128.or : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Or(Vector128 left, Vector128 right) => Or(left, right); /// /// v128_t wasm_v128_or (v128_t a, v128_t b) /// v128.or : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Or(Vector128 left, Vector128 right) => Or(left, right); /// /// v128_t wasm_v128_or (v128_t a, v128_t b) /// v128.or : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Or(Vector128 left, Vector128 right) => Or(left, right); /// /// v128_t wasm_v128_or (v128_t a, v128_t b) /// v128.or : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Or(Vector128 left, Vector128 right) => Or(left, right); /// /// v128_t wasm_v128_or (v128_t a, v128_t b) /// v128.or : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Or(Vector128 left, Vector128 right) => Or(left, right); /// /// v128_t wasm_v128_xor (v128_t a, v128_t b) /// v128.xor : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Xor(Vector128 left, Vector128 right) => Xor(left, right); /// /// v128_t wasm_v128_xor (v128_t a, v128_t b) /// v128.xor : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Xor(Vector128 left, Vector128 right) => Xor(left, right); /// /// v128_t wasm_v128_xor (v128_t a, v128_t b) /// v128.xor : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Xor(Vector128 left, Vector128 right) => Xor(left, right); /// /// v128_t wasm_v128_xor (v128_t a, v128_t b) /// v128.xor : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Xor(Vector128 left, Vector128 right) => Xor(left, right); /// /// v128_t wasm_v128_xor (v128_t a, v128_t b) /// v128.xor : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Xor(Vector128 left, Vector128 right) => Xor(left, right); /// /// v128_t wasm_v128_xor (v128_t a, v128_t b) /// v128.xor : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Xor(Vector128 left, Vector128 right) => Xor(left, right); /// /// v128_t wasm_v128_xor (v128_t a, v128_t b) /// v128.xor : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Xor(Vector128 left, Vector128 right) => Xor(left, right); /// /// v128_t wasm_v128_xor (v128_t a, v128_t b) /// v128.xor : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Xor(Vector128 left, Vector128 right) => Xor(left, right); /// /// v128_t wasm_v128_xor (v128_t a, v128_t b) /// v128.xor : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Xor(Vector128 left, Vector128 right) => Xor(left, right); /// /// v128_t wasm_v128_xor (v128_t a, v128_t b) /// v128.xor : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Xor(Vector128 left, Vector128 right) => Xor(left, right); /// /// v128_t wasm_v128_xor (v128_t a, v128_t b) /// v128.xor : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Xor(Vector128 left, Vector128 right) => Xor(left, right); /// /// v128_t wasm_v128_xor (v128_t a, v128_t b) /// v128.xor : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Xor(Vector128 left, Vector128 right) => Xor(left, right); /// /// v128_t wasm_v128_not (v128_t a) /// v128.not : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Not(Vector128 value) => Not(value); /// /// v128_t wasm_v128_not (v128_t a) /// v128.not : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Not(Vector128 value) => Not(value); /// /// v128_t wasm_v128_not (v128_t a) /// v128.not : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Not(Vector128 value) => Not(value); /// /// v128_t wasm_v128_not (v128_t a) /// v128.not : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Not(Vector128 value) => Not(value); /// /// v128_t wasm_v128_not (v128_t a) /// v128.not : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Not(Vector128 value) => Not(value); /// /// v128_t wasm_v128_not (v128_t a) /// v128.not : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Not(Vector128 value) => Not(value); /// /// v128_t wasm_v128_not (v128_t a) /// v128.not : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Not(Vector128 value) => Not(value); /// /// v128_t wasm_v128_not (v128_t a) /// v128.not : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Not(Vector128 value) => Not(value); /// /// v128_t wasm_v128_not (v128_t a) /// v128.not : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Not(Vector128 value) => Not(value); /// /// v128_t wasm_v128_not (v128_t a) /// v128.not : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Not(Vector128 value) => Not(value); /// /// v128_t wasm_v128_not (v128_t a) /// v128.not : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Not(Vector128 value) => Not(value); /// /// v128_t wasm_v128_not (v128_t a) /// v128.not : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Not(Vector128 value) => Not(value); /// /// v128_t wasm_v128_andnot (v128_t a, v128_t b) /// v128.andnot : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 AndNot(Vector128 left, Vector128 right) => AndNot(left, right); /// /// v128_t wasm_v128_andnot (v128_t a, v128_t b) /// v128.andnot : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 AndNot(Vector128 left, Vector128 right) => AndNot(left, right); /// /// v128_t wasm_v128_andnot (v128_t a, v128_t b) /// v128.andnot : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 AndNot(Vector128 left, Vector128 right) => AndNot(left, right); /// /// v128_t wasm_v128_andnot (v128_t a, v128_t b) /// v128.andnot : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 AndNot(Vector128 left, Vector128 right) => AndNot(left, right); /// /// v128_t wasm_v128_andnot (v128_t a, v128_t b) /// v128.andnot : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 AndNot(Vector128 left, Vector128 right) => AndNot(left, right); /// /// v128_t wasm_v128_andnot (v128_t a, v128_t b) /// v128.andnot : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 AndNot(Vector128 left, Vector128 right) => AndNot(left, right); /// /// v128_t wasm_v128_andnot (v128_t a, v128_t b) /// v128.andnot : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 AndNot(Vector128 left, Vector128 right) => AndNot(left, right); /// /// v128_t wasm_v128_andnot (v128_t a, v128_t b) /// v128.andnot : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 AndNot(Vector128 left, Vector128 right) => AndNot(left, right); /// /// v128_t wasm_v128_andnot (v128_t a, v128_t b) /// v128.andnot : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 AndNot(Vector128 left, Vector128 right) => AndNot(left, right); /// /// v128_t wasm_v128_andnot (v128_t a, v128_t b) /// v128.andnot : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 AndNot(Vector128 left, Vector128 right) => AndNot(left, right); /// /// v128_t wasm_v128_andnot (v128_t a, v128_t b) /// v128.andnot : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 AndNot(Vector128 left, Vector128 right) => AndNot(left, right); /// /// v128_t wasm_v128_andnot (v128_t a, v128_t b) /// v128.andnot : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 AndNot(Vector128 left, Vector128 right) => AndNot(left, right); /// /// v128_t wasm_v128_bitselect (v128_t a, v128_t b, v128_t mask) /// v128.bitselect : [v128 v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 BitwiseSelect(Vector128 left, Vector128 right, Vector128 select) => BitwiseSelect(left, right, select); /// /// v128_t wasm_v128_bitselect (v128_t a, v128_t b, v128_t mask) /// v128.bitselect : [v128 v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 BitwiseSelect(Vector128 left, Vector128 right, Vector128 select) => BitwiseSelect(left, right, select); /// /// v128_t wasm_v128_bitselect (v128_t a, v128_t b, v128_t mask) /// v128.bitselect : [v128 v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 BitwiseSelect(Vector128 left, Vector128 right, Vector128 select) => BitwiseSelect(left, right, select); /// /// v128_t wasm_v128_bitselect (v128_t a, v128_t b, v128_t mask) /// v128.bitselect : [v128 v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 BitwiseSelect(Vector128 left, Vector128 right, Vector128 select) => BitwiseSelect(left, right, select); /// /// v128_t wasm_v128_bitselect (v128_t a, v128_t b, v128_t mask) /// v128.bitselect : [v128 v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 BitwiseSelect(Vector128 left, Vector128 right, Vector128 select) => BitwiseSelect(left, right, select); /// /// v128_t wasm_v128_bitselect (v128_t a, v128_t b, v128_t mask) /// v128.bitselect : [v128 v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 BitwiseSelect(Vector128 left, Vector128 right, Vector128 select) => BitwiseSelect(left, right, select); /// /// v128_t wasm_v128_bitselect (v128_t a, v128_t b, v128_t mask) /// v128.bitselect : [v128 v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 BitwiseSelect(Vector128 left, Vector128 right, Vector128 select) => BitwiseSelect(left, right, select); /// /// v128_t wasm_v128_bitselect (v128_t a, v128_t b, v128_t mask) /// v128.bitselect : [v128 v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 BitwiseSelect(Vector128 left, Vector128 right, Vector128 select) => BitwiseSelect(left, right, select); /// /// v128_t wasm_v128_bitselect (v128_t a, v128_t b, v128_t mask) /// v128.bitselect : [v128 v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 BitwiseSelect(Vector128 left, Vector128 right, Vector128 select) => BitwiseSelect(left, right, select); /// /// v128_t wasm_v128_bitselect (v128_t a, v128_t b, v128_t mask) /// v128.bitselect : [v128 v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 BitwiseSelect(Vector128 left, Vector128 right, Vector128 select) => BitwiseSelect(left, right, select); /// /// v128_t wasm_v128_bitselect (v128_t a, v128_t b, v128_t mask) /// v128.bitselect : [v128 v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 BitwiseSelect(Vector128 left, Vector128 right, Vector128 select) => BitwiseSelect(left, right, select); /// /// v128_t wasm_v128_bitselect (v128_t a, v128_t b, v128_t mask) /// v128.bitselect : [v128 v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 BitwiseSelect(Vector128 left, Vector128 right, Vector128 select) => BitwiseSelect(left, right, select); /// /// v128_t wasm_i8x16_popcnt (v128_t a) /// i8x16.popcnt : [v128] -> [v128] /// - [Intrinsic] public static Vector128 PopCount(Vector128 value) => PopCount(value); // Boolean horizontal reductions @@ -1398,134 +1200,112 @@ public abstract class PackedSimd /// bool wasm_v128_any_true (v128_t a) /// v128.any_true : [v128] -> [i32] /// - [Intrinsic] public static bool AnyTrue(Vector128 value) => AnyTrue(value); /// /// bool wasm_v128_any_true (v128_t a) /// v128.any_true : [v128] -> [i32] /// - [Intrinsic] public static bool AnyTrue(Vector128 value) => AnyTrue(value); /// /// bool wasm_v128_any_true (v128_t a) /// v128.any_true : [v128] -> [i32] /// - [Intrinsic] public static bool AnyTrue(Vector128 value) => AnyTrue(value); /// /// bool wasm_v128_any_true (v128_t a) /// v128.any_true : [v128] -> [i32] /// - [Intrinsic] public static bool AnyTrue(Vector128 value) => AnyTrue(value); /// /// bool wasm_v128_any_true (v128_t a) /// v128.any_true : [v128] -> [i32] /// - [Intrinsic] public static bool AnyTrue(Vector128 value) => AnyTrue(value); /// /// bool wasm_v128_any_true (v128_t a) /// v128.any_true : [v128] -> [i32] /// - [Intrinsic] public static bool AnyTrue(Vector128 value) => AnyTrue(value); /// /// bool wasm_v128_any_true (v128_t a) /// v128.any_true : [v128] -> [i32] /// - [Intrinsic] public static bool AnyTrue(Vector128 value) => AnyTrue(value); /// /// bool wasm_v128_any_true (v128_t a) /// v128.any_true : [v128] -> [i32] /// - [Intrinsic] public static bool AnyTrue(Vector128 value) => AnyTrue(value); /// /// bool wasm_v128_any_true (v128_t a) /// v128.any_true : [v128] -> [i32] /// - [Intrinsic] public static bool AnyTrue(Vector128 value) => AnyTrue(value); /// /// bool wasm_v128_any_true (v128_t a) /// v128.any_true : [v128] -> [i32] /// - [Intrinsic] public static bool AnyTrue(Vector128 value) => AnyTrue(value); /// /// bool wasm_v128_any_true (v128_t a) /// v128.any_true : [v128] -> [i32] /// - [Intrinsic] public static bool AnyTrue(Vector128 value) => AnyTrue(value); /// /// bool wasm_v128_any_true (v128_t a) /// v128.any_true : [v128] -> [i32] /// - [Intrinsic] public static bool AnyTrue(Vector128 value) => AnyTrue(value); /// /// bool wasm_i8x16_all_true (v128_t a) /// i8x16.all_true : [v128] -> [i32] /// - [Intrinsic] public static bool AllTrue(Vector128 value) => AllTrue(value); /// /// bool wasm_i8x16_all_true (v128_t a) /// i8x16.all_true : [v128] -> [i32] /// - [Intrinsic] public static bool AllTrue(Vector128 value) => AllTrue(value); /// /// bool wasm_i16x8_all_true (v128_t a) /// i16x8.all_true : [v128] -> [i32] /// - [Intrinsic] public static bool AllTrue(Vector128 value) => AllTrue(value); /// /// bool wasm_i16x8_all_true (v128_t a) /// i16x8.all_true : [v128] -> [i32] /// - [Intrinsic] public static bool AllTrue(Vector128 value) => AllTrue(value); /// /// bool wasm_i32x4_all_true (v128_t a) /// i32x4.all_true : [v128] -> [i32] /// - [Intrinsic] public static bool AllTrue(Vector128 value) => AllTrue(value); /// /// bool wasm_i32x4_all_true (v128_t a) /// i32x4.all_true : [v128] -> [i32] /// - [Intrinsic] public static bool AllTrue(Vector128 value) => AllTrue(value); /// /// bool wasm_i64x2_all_true (v128_t a) /// i64x2.all_true : [v128] -> [i32] /// - [Intrinsic] public static bool AllTrue(Vector128 value) => AllTrue(value); /// /// bool wasm_i64x2_all_true (v128_t a) /// i64x2.all_true : [v128] -> [i32] /// - [Intrinsic] public static bool AllTrue(Vector128 value) => AllTrue(value); /// /// bool wasm_i32x4_all_true (v128_t a) /// i32x4.all_true : [v128] -> [i32] /// - [Intrinsic] public static bool AllTrue(Vector128 value) => AllTrue(value); /// /// bool wasm_i32x4_all_true (v128_t a) /// i32x4.all_true : [v128] -> [i32] /// - [Intrinsic] public static bool AllTrue(Vector128 value) => AllTrue(value); // Bitmask extraction @@ -1534,61 +1314,51 @@ public abstract class PackedSimd /// uint32_t wasm_i8x16_bitmask (v128_t a) /// i8x16.bitmask : [v128] -> [i32] /// - [Intrinsic] public static int Bitmask(Vector128 value) => Bitmask(value); /// /// uint32_t wasm_i8x16_bitmask (v128_t a) /// i8x16.bitmask : [v128] -> [i32] /// - [Intrinsic] public static int Bitmask(Vector128 value) => Bitmask(value); /// /// uint32_t wasm_i16x8_bitmask (v128_t a) /// i16x8.bitmask : [v128] -> [i32] /// - [Intrinsic] public static int Bitmask(Vector128 value) => Bitmask(value); /// /// uint32_t wasm_i16x8_bitmask (v128_t a) /// i16x8.bitmask : [v128] -> [i32] /// - [Intrinsic] public static int Bitmask(Vector128 value) => Bitmask(value); /// /// uint32_t wasm_i32x4_bitmask (v128_t a) /// i32x4.bitmask : [v128] -> [i32] /// - [Intrinsic] public static int Bitmask(Vector128 value) => Bitmask(value); /// /// uint32_t wasm_i32x4_bitmask (v128_t a) /// i32x4.bitmask : [v128] -> [i32] /// - [Intrinsic] public static int Bitmask(Vector128 value) => Bitmask(value); /// /// uint32_t wasm_i64x2_bitmask (v128_t a) /// i64x2.bitmask : [v128] -> [i32] /// - [Intrinsic] public static int Bitmask(Vector128 value) => Bitmask(value); /// /// uint32_t wasm_i64x2_bitmask (v128_t a) /// i64x2.bitmask : [v128] -> [i32] /// - [Intrinsic] public static int Bitmask(Vector128 value) => Bitmask(value); /// /// uint32_t wasm_i32x4_bitmask (v128_t a) /// i32x4.bitmask : [v128] -> [i32] /// - [Intrinsic] public static int Bitmask(Vector128 value) => Bitmask(value); /// /// uint32_t wasm_i32x4_bitmask (v128_t a) /// i32x4.bitmask : [v128] -> [i32] /// - [Intrinsic] public static int Bitmask(Vector128 value) => Bitmask(value); // Comparisons @@ -1597,420 +1367,351 @@ public abstract class PackedSimd /// v128_t wasm_i8x16_eq (v128_t a, v128_t b) /// i8x16.eq : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareEqual(Vector128 left, Vector128 right) => CompareEqual(left, right); /// /// v128_t wasm_i8x16_eq (v128_t a, v128_t b) /// i8x16.eq : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareEqual(Vector128 left, Vector128 right) => CompareEqual(left, right); /// /// v128_t wasm_i16x8_eq (v128_t a, v128_t b) /// i16x8.eq : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareEqual(Vector128 left, Vector128 right) => CompareEqual(left, right); /// /// v128_t wasm_i16x8_eq (v128_t a, v128_t b) /// i16x8.eq : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareEqual(Vector128 left, Vector128 right) => CompareEqual(left, right); /// /// v128_t wasm_i32x4_eq (v128_t a, v128_t b) /// i32x4.eq : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareEqual(Vector128 left, Vector128 right) => CompareEqual(left, right); /// /// v128_t wasm_i32x4_eq (v128_t a, v128_t b) /// i32x4.eq : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareEqual(Vector128 left, Vector128 right) => CompareEqual(left, right); /// /// v128_t wasm_i64x2_eq (v128_t a, v128_t b) /// i64x2.eq : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareEqual(Vector128 left, Vector128 right) => CompareEqual(left, right); /// /// v128_t wasm_i64x2_eq (v128_t a, v128_t b) /// i64x2.eq : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareEqual(Vector128 left, Vector128 right) => CompareEqual(left, right); /// /// v128_t wasm_f32x4_eq (v128_t a, v128_t b) /// f32x4.eq : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareEqual(Vector128 left, Vector128 right) => CompareEqual(left, right); /// /// v128_t wasm_f64x2_eq (v128_t a, v128_t b) /// f64x2.eq : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareEqual(Vector128 left, Vector128 right) => CompareEqual(left, right); /// /// v128_t wasm_i32x4_eq (v128_t a, v128_t b) /// i32x4.eq : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareEqual(Vector128 left, Vector128 right) => CompareEqual(left, right); /// /// v128_t wasm_i32x4_eq (v128_t a, v128_t b) /// i32x4.eq : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareEqual(Vector128 left, Vector128 right) => CompareEqual(left, right); /// /// v128_t wasm_i8x16_ne (v128_t a, v128_t b) /// i8x16.ne : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareNotEqual(Vector128 left, Vector128 right) => CompareNotEqual(left, right); /// /// v128_t wasm_i8x16_ne (v128_t a, v128_t b) /// i8x16.ne : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareNotEqual(Vector128 left, Vector128 right) => CompareNotEqual(left, right); /// /// v128_t wasm_i16x8_ne (v128_t a, v128_t b) /// i16x8.ne : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareNotEqual(Vector128 left, Vector128 right) => CompareNotEqual(left, right); /// /// v128_t wasm_i16x8_ne (v128_t a, v128_t b) /// i16x8.ne : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareNotEqual(Vector128 left, Vector128 right) => CompareNotEqual(left, right); /// /// v128_t wasm_i32x4_ne (v128_t a, v128_t b) /// i32x4.ne : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareNotEqual(Vector128 left, Vector128 right) => CompareNotEqual(left, right); /// /// v128_t wasm_i32x4_ne (v128_t a, v128_t b) /// i32x4.ne : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareNotEqual(Vector128 left, Vector128 right) => CompareNotEqual(left, right); /// /// v128_t wasm_i64x2_ne (v128_t a, v128_t b) /// i64x2.ne : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareNotEqual(Vector128 left, Vector128 right) => CompareNotEqual(left, right); /// /// v128_t wasm_i64x2_ne (v128_t a, v128_t b) /// i64x2.ne : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareNotEqual(Vector128 left, Vector128 right) => CompareNotEqual(left, right); /// /// v128_t wasm_f32x4_ne (v128_t a, v128_t b) /// f32x4.ne : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareNotEqual(Vector128 left, Vector128 right) => CompareNotEqual(left, right); /// /// v128_t wasm_f64x2_ne (v128_t a, v128_t b) /// f64x2.ne : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareNotEqual(Vector128 left, Vector128 right) => CompareNotEqual(left, right); /// /// v128_t wasm_i32x4_ne (v128_t a, v128_t b) /// i32x4.ne : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareNotEqual(Vector128 left, Vector128 right) => CompareNotEqual(left, right); /// /// v128_t wasm_i32x4_ne (v128_t a, v128_t b) /// i32x4.ne : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareNotEqual(Vector128 left, Vector128 right) => CompareNotEqual(left, right); /// /// v128_t wasm_i8x16_lt (v128_t a, v128_t b) /// i8x16.lt_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThan(Vector128 left, Vector128 right) => CompareLessThan(left, right); /// /// v128_t wasm_u8x16_lt (v128_t a, v128_t b) /// i8x16.lt_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThan(Vector128 left, Vector128 right) => CompareLessThan(left, right); /// /// v128_t wasm_i16x8_lt (v128_t a, v128_t b) /// i16x8.lt_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThan(Vector128 left, Vector128 right) => CompareLessThan(left, right); /// /// v128_t wasm_u16x8_lt (v128_t a, v128_t b) /// i16x8.lt_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThan(Vector128 left, Vector128 right) => CompareLessThan(left, right); /// /// v128_t wasm_i32x4_lt (v128_t a, v128_t b) /// i32x4.lt_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThan(Vector128 left, Vector128 right) => CompareLessThan(left, right); /// /// v128_t wasm_u32x4_lt (v128_t a, v128_t b) /// i32x4.lt_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThan(Vector128 left, Vector128 right) => CompareLessThan(left, right); /// /// v128_t wasm_i64x2_lt (v128_t a, v128_t b) /// i64x2.lt_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThan(Vector128 left, Vector128 right) => CompareLessThan(left, right); /// /// i64x2.lt_s : [v128 v128] -> [v128] /// No unsigned i64x2 comparison instruction exists; the sign bit of each operand is flipped before the signed comparison. /// - [Intrinsic] public static Vector128 CompareLessThan(Vector128 left, Vector128 right) => CompareLessThan(left, right); /// /// v128_t wasm_f32x4_lt (v128_t a, v128_t b) /// f32x4.lt : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThan(Vector128 left, Vector128 right) => CompareLessThan(left, right); /// /// v128_t wasm_f64x2_lt (v128_t a, v128_t b) /// f64x2.lt : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThan(Vector128 left, Vector128 right) => CompareLessThan(left, right); /// /// v128_t wasm_i32x4_lt (v128_t a, v128_t b) /// i32x4.lt_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThan(Vector128 left, Vector128 right) => CompareLessThan(left, right); /// /// v128_t wasm_u32x4_lt (v128_t a, v128_t b) /// i32x4.lt_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThan(Vector128 left, Vector128 right) => CompareLessThan(left, right); /// /// v128_t wasm_i8x16_le (v128_t a, v128_t b) /// i8x16.le_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThanOrEqual(Vector128 left, Vector128 right) => CompareLessThanOrEqual(left, right); /// /// v128_t wasm_u8x16_le (v128_t a, v128_t b) /// i8x16.le_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThanOrEqual(Vector128 left, Vector128 right) => CompareLessThanOrEqual(left, right); /// /// v128_t wasm_i16x8_le (v128_t a, v128_t b) /// i16x8.le_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThanOrEqual(Vector128 left, Vector128 right) => CompareLessThanOrEqual(left, right); /// /// v128_t wasm_u16x8_le (v128_t a, v128_t b) /// i16x8.le_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThanOrEqual(Vector128 left, Vector128 right) => CompareLessThanOrEqual(left, right); /// /// v128_t wasm_i32x4_le (v128_t a, v128_t b) /// i32x4.le_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThanOrEqual(Vector128 left, Vector128 right) => CompareLessThanOrEqual(left, right); /// /// v128_t wasm_u32x4_le (v128_t a, v128_t b) /// i32x4.le_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThanOrEqual(Vector128 left, Vector128 right) => CompareLessThanOrEqual(left, right); /// /// v128_t wasm_i64x2_le (v128_t a, v128_t b) /// i64x2.le_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThanOrEqual(Vector128 left, Vector128 right) => CompareLessThanOrEqual(left, right); /// /// i64x2.le_s : [v128 v128] -> [v128] /// No unsigned i64x2 comparison instruction exists; the sign bit of each operand is flipped before the signed comparison. /// - [Intrinsic] public static Vector128 CompareLessThanOrEqual(Vector128 left, Vector128 right) => CompareLessThanOrEqual(left, right); /// /// v128_t wasm_f32x4_le (v128_t a, v128_t b) /// f32x4.le : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThanOrEqual(Vector128 left, Vector128 right) => CompareLessThanOrEqual(left, right); /// /// v128_t wasm_f64x2_le (v128_t a, v128_t b) /// f64x2.le : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThanOrEqual(Vector128 left, Vector128 right) => CompareLessThanOrEqual(left, right); /// /// v128_t wasm_i32x4_le (v128_t a, v128_t b) /// i32x4.le_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThanOrEqual(Vector128 left, Vector128 right) => CompareLessThanOrEqual(left, right); /// /// v128_t wasm_u32x4_le (v128_t a, v128_t b) /// i32x4.le_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareLessThanOrEqual(Vector128 left, Vector128 right) => CompareLessThanOrEqual(left, right); /// /// v128_t wasm_i8x16_gt (v128_t a, v128_t b) /// i8x16.gt_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThan(Vector128 left, Vector128 right) => CompareGreaterThan(left, right); /// /// v128_t wasm_u8x16_gt (v128_t a, v128_t b) /// i8x16.gt_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThan(Vector128 left, Vector128 right) => CompareGreaterThan(left, right); /// /// v128_t wasm_i16x8_gt (v128_t a, v128_t b) /// i16x8.gt_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThan(Vector128 left, Vector128 right) => CompareGreaterThan(left, right); /// /// v128_t wasm_u16x8_gt (v128_t a, v128_t b) /// i16x8.gt_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThan(Vector128 left, Vector128 right) => CompareGreaterThan(left, right); /// /// v128_t wasm_i32x4_gt (v128_t a, v128_t b) /// i32x4.gt_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThan(Vector128 left, Vector128 right) => CompareGreaterThan(left, right); /// /// v128_t wasm_u32x4_gt (v128_t a, v128_t b) /// i32x4.gt_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThan(Vector128 left, Vector128 right) => CompareGreaterThan(left, right); /// /// v128_t wasm_i64x2_gt (v128_t a, v128_t b) /// i64x2.gt_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThan(Vector128 left, Vector128 right) => CompareGreaterThan(left, right); /// /// i64x2.gt_s : [v128 v128] -> [v128] /// No unsigned i64x2 comparison instruction exists; the sign bit of each operand is flipped before the signed comparison. /// - [Intrinsic] public static Vector128 CompareGreaterThan(Vector128 left, Vector128 right) => CompareGreaterThan(left, right); /// /// v128_t wasm_f32x4_gt (v128_t a, v128_t b) /// f32x4.gt : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThan(Vector128 left, Vector128 right) => CompareGreaterThan(left, right); /// /// v128_t wasm_f64x2_gt (v128_t a, v128_t b) /// f64x2.gt : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThan(Vector128 left, Vector128 right) => CompareGreaterThan(left, right); /// /// v128_t wasm_i32x4_gt (v128_t a, v128_t b) /// i32x4.gt_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThan(Vector128 left, Vector128 right) => CompareGreaterThan(left, right); /// /// v128_t wasm_u32x4_gt (v128_t a, v128_t b) /// i32x4.gt_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThan(Vector128 left, Vector128 right) => CompareGreaterThan(left, right); /// /// v128_t wasm_i8x16_ge (v128_t a, v128_t b) /// i8x16.ge_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareGreaterThanOrEqual(left, right); /// /// v128_t wasm_u8x16_ge (v128_t a, v128_t b) /// i8x16.ge_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareGreaterThanOrEqual(left, right); /// /// v128_t wasm_i16x8_ge (v128_t a, v128_t b) /// i16x8.ge_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareGreaterThanOrEqual(left, right); /// /// v128_t wasm_u16x8_ge (v128_t a, v128_t b) /// i16x8.ge_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareGreaterThanOrEqual(left, right); /// /// v128_t wasm_i32x4_ge (v128_t a, v128_t b) /// i32x4.ge_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareGreaterThanOrEqual(left, right); /// /// v128_t wasm_u32x4_ge (v128_t a, v128_t b) /// i32x4.ge_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareGreaterThanOrEqual(left, right); /// /// v128_t wasm_i64x2_ge (v128_t a, v128_t b) /// i64x2.ge_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareGreaterThanOrEqual(left, right); /// /// i64x2.ge_s : [v128 v128] -> [v128] /// No unsigned i64x2 comparison instruction exists; the sign bit of each operand is flipped before the signed comparison. /// - [Intrinsic] public static Vector128 CompareGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareGreaterThanOrEqual(left, right); /// /// v128_t wasm_f32x4_ge (v128_t a, v128_t b) /// f32x4.ge : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareGreaterThanOrEqual(left, right); /// /// v128_t wasm_f64x2_ge (v128_t a, v128_t b) @@ -2021,13 +1722,11 @@ public abstract class PackedSimd /// v128_t wasm_i32x4_ge (v128_t a, v128_t b) /// i32x4.ge_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareGreaterThanOrEqual(left, right); /// /// v128_t wasm_u32x4_ge (v128_t a, v128_t b) /// i32x4.ge_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 CompareGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareGreaterThanOrEqual(left, right); // Load @@ -2036,268 +1735,224 @@ public abstract class PackedSimd /// v128_t wasm_v128_load (const void *mem) /// v128.load memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadVector128(sbyte* address) => LoadVector128(address); /// /// v128_t wasm_v128_load (const void *mem) /// v128.load memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadVector128(byte* address) => LoadVector128(address); /// /// v128_t wasm_v128_load (const void *mem) /// v128.load memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadVector128(short* address) => LoadVector128(address); /// /// v128_t wasm_v128_load (const void *mem) /// v128.load memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadVector128(ushort* address) => LoadVector128(address); /// /// v128_t wasm_v128_load (const void *mem) /// v128.load memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadVector128(int* address) => LoadVector128(address); /// /// v128_t wasm_v128_load (const void *mem) /// v128.load memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadVector128(uint* address) => LoadVector128(address); /// /// v128_t wasm_v128_load (const void *mem) /// v128.load memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadVector128(long* address) => LoadVector128(address); /// /// v128_t wasm_v128_load (const void *mem) /// v128.load memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadVector128(ulong* address) => LoadVector128(address); /// /// v128_t wasm_v128_load (const void *mem) /// v128.load memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadVector128(float* address) => LoadVector128(address); /// /// v128_t wasm_v128_load (const void *mem) /// v128.load memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadVector128(double* address) => LoadVector128(address); /// /// v128_t wasm_v128_load (const void *mem) /// v128.load memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadVector128(nint* address) => LoadVector128(address); /// /// v128_t wasm_v128_load (const void *mem) /// v128.load memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadVector128(nuint* address) => LoadVector128(address); /// /// v128_t wasm_v128_load32_zero (const void *mem) /// v128.load32_zero memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarVector128(int* address) => LoadScalarVector128(address); /// /// v128_t wasm_v128_load32_zero (const void *mem) /// v128.load32_zero memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarVector128(uint* address) => LoadScalarVector128(address); /// /// v128_t wasm_v128_load64_zero (const void *mem) /// v128.load64_zero memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarVector128(long* address) => LoadScalarVector128(address); /// /// v128_t wasm_v128_load64_zero (const void *mem) /// v128.load64_zero memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarVector128(ulong* address) => LoadScalarVector128(address); /// /// v128_t wasm_v128_load32_zero (const void *mem) /// v128.load32_zero memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarVector128(float* address) => LoadScalarVector128(address); /// /// v128_t wasm_v128_load64_zero (const void *mem) /// v128.load64_zero memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarVector128(double* address) => LoadScalarVector128(address); /// /// v128_t wasm_v128_load32_zero (const void *mem) /// v128.load32_zero memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarVector128(nint* address) => LoadScalarVector128(address); /// /// v128_t wasm_v128_load32_zero (const void *mem) /// v128.load32_zero memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarVector128(nuint* address) => LoadScalarVector128(address); /// /// v128_t wasm_v128_load8_splat (const void *mem) /// v128.load8_splat memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndSplatVector128(sbyte* address) => LoadScalarAndSplatVector128(address); /// /// v128_t wasm_v128_load8_splat (const void *mem) /// v128.load8_splat memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndSplatVector128(byte* address) => LoadScalarAndSplatVector128(address); /// /// v128_t wasm_v128_load16_splat (const void *mem) /// v128.load16_splat memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndSplatVector128(short* address) => LoadScalarAndSplatVector128(address); /// /// v128_t wasm_v128_load16_splat (const void *mem) /// v128.load16_splat memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndSplatVector128(ushort* address) => LoadScalarAndSplatVector128(address); /// /// v128_t wasm_v128_load32_splat (const void *mem) /// v128.load32_splat memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndSplatVector128(int* address) => LoadScalarAndSplatVector128(address); /// /// v128_t wasm_v128_load32_splat (const void *mem) /// v128.load32_splat memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndSplatVector128(uint* address) => LoadScalarAndSplatVector128(address); /// /// v128_t wasm_v128_load64_splat (const void *mem) /// v128.load64_splat memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndSplatVector128(long* address) => LoadScalarAndSplatVector128(address); /// /// v128_t wasm_v128_load64_splat (const void *mem) /// v128.load64_splat memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndSplatVector128(ulong* address) => LoadScalarAndSplatVector128(address); /// /// v128_t wasm_v128_load32_splat (const void *mem) /// v128.load32_splat memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndSplatVector128(float* address) => LoadScalarAndSplatVector128(address); /// /// v128_t wasm_v128_load64_splat (const void *mem) /// v128.load64_splat memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndSplatVector128(double* address) => LoadScalarAndSplatVector128(address); /// /// v128_t wasm_v128_load32_splat (const void *mem) /// v128.load32_splat memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndSplatVector128(nint* address) => LoadScalarAndSplatVector128(address); /// /// v128_t wasm_v128_load32_splat (const void *mem) /// v128.load32_splat memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndSplatVector128(nuint* address) => LoadScalarAndSplatVector128(address); /// /// v128_t wasm_v128_load8_lane (const void *mem, v128_t vec, int i) /// v128.load8_lane memarg laneidx : [i32 v128] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndInsert(sbyte* address, Vector128 vector, [ConstantExpected(Max = (byte)(15))] byte index) => LoadScalarAndInsert(address, vector, index); // takes ImmLaneIdx16 /// /// v128_t wasm_v128_load8_lane (const void *mem, v128_t vec, int i) /// v128.load8_lane memarg laneidx : [i32 v128] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndInsert(byte* address, Vector128 vector, [ConstantExpected(Max = (byte)(15))] byte index) => LoadScalarAndInsert(address, vector, index); // takes ImmLaneIdx16 /// /// v128_t wasm_v128_load16_lane (const void *mem, v128_t vec, int i) /// v128.load16_lane memarg laneidx : [i32 v128] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndInsert(short* address, Vector128 vector, [ConstantExpected(Max = (byte)(7))] byte index) => LoadScalarAndInsert(address, vector, index); // takes ImmLaneIdx8 /// /// v128_t wasm_v128_load16_lane (const void *mem, v128_t vec, int i) /// v128.load16_lane memarg laneidx : [i32 v128] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndInsert(ushort* address, Vector128 vector, [ConstantExpected(Max = (byte)(7))] byte index) => LoadScalarAndInsert(address, vector, index); // takes ImmLaneIdx8 /// /// v128_t wasm_v128_load32_lane (const void *mem, v128_t vec, int i) /// v128.load32_lane memarg laneidx : [i32 v128] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndInsert(int* address, Vector128 vector, [ConstantExpected(Max = (byte)(3))] byte index) => LoadScalarAndInsert(address, vector, index); // takes ImmLaneIdx4 /// /// v128_t wasm_v128_load32_lane (const void *mem, v128_t vec, int i) /// v128.load32_lane memarg laneidx : [i32 v128] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndInsert(uint* address, Vector128 vector, [ConstantExpected(Max = (byte)(3))] byte index) => LoadScalarAndInsert(address, vector, index); // takes ImmLaneIdx4 /// /// v128_t wasm_v128_load64_lane (const void *mem, v128_t vec, int i) /// v128.load64_lane memarg laneidx : [i32 v128] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndInsert(long* address, Vector128 vector, [ConstantExpected(Max = (byte)(1))] byte index) => LoadScalarAndInsert(address, vector, index); // takes ImmLaneIdx2 /// /// v128_t wasm_v128_load64_lane (const void *mem, v128_t vec, int i) /// v128.load64_lane memarg laneidx : [i32 v128] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndInsert(ulong* address, Vector128 vector, [ConstantExpected(Max = (byte)(1))] byte index) => LoadScalarAndInsert(address, vector, index); // takes ImmLaneIdx2 /// /// v128_t wasm_v128_load32_lane (const void *mem, v128_t vec, int i) /// v128.load32_lane memarg laneidx : [i32 v128] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndInsert(float* address, Vector128 vector, [ConstantExpected(Max = (byte)(3))] byte index) => LoadScalarAndInsert(address, vector, index); // takes ImmLaneIdx4 /// /// v128_t wasm_v128_load64_lane (const void *mem, v128_t vec, int i) /// v128.load64_lane memarg laneidx : [i32 v128] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndInsert(double* address, Vector128 vector, [ConstantExpected(Max = (byte)(1))] byte index) => LoadScalarAndInsert(address, vector, index); // takes ImmLaneIdx2 /// /// v128_t wasm_v128_load32_lane (const void *mem, v128_t vec, int i) /// v128.load32_lane memarg laneidx : [i32 v128] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndInsert(nint* address, Vector128 vector, [ConstantExpected(Max = (byte)(3))] byte index) => LoadScalarAndInsert(address, vector, index); // takes ImmLaneIdx4 /// /// v128_t wasm_v128_load32_lane (const void *mem, v128_t vec, int i) /// v128.load32_lane memarg laneidx : [i32 v128] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadScalarAndInsert(nuint* address, Vector128 vector, [ConstantExpected(Max = (byte)(3))] byte index) => LoadScalarAndInsert(address, vector, index); // takes ImmLaneIdx4 // Store @@ -2306,183 +1961,153 @@ public abstract class PackedSimd /// void wasm_v128_store (void *mem, v128_t a) /// v128.store memarg : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void Store(sbyte* address, Vector128 source) => Store(address, source); /// /// void wasm_v128_store (void *mem, v128_t a) /// v128.store memarg : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void Store(byte* address, Vector128 source) => Store(address, source); /// /// void wasm_v128_store (void *mem, v128_t a) /// v128.store memarg : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void Store(short* address, Vector128 source) => Store(address, source); /// /// void wasm_v128_store (void *mem, v128_t a) /// v128.store memarg : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void Store(ushort* address, Vector128 source) => Store(address, source); /// /// void wasm_v128_store (void *mem, v128_t a) /// v128.store memarg : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void Store(int* address, Vector128 source) => Store(address, source); /// /// void wasm_v128_store (void *mem, v128_t a) /// v128.store memarg : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void Store(uint* address, Vector128 source) => Store(address, source); /// /// void wasm_v128_store (void *mem, v128_t a) /// v128.store memarg : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void Store(long* address, Vector128 source) => Store(address, source); /// /// void wasm_v128_store (void *mem, v128_t a) /// v128.store memarg : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void Store(ulong* address, Vector128 source) => Store(address, source); /// /// void wasm_v128_store (void *mem, v128_t a) /// v128.store memarg : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void Store(float* address, Vector128 source) => Store(address, source); /// /// void wasm_v128_store (void *mem, v128_t a) /// v128.store memarg : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void Store(double* address, Vector128 source) => Store(address, source); /// /// void wasm_v128_store (void *mem, v128_t a) /// v128.store memarg : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void Store(nint* address, Vector128 source) => Store(address, source); /// /// void wasm_v128_store (void *mem, v128_t a) /// v128.store memarg : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void Store(nuint* address, Vector128 source) => Store(address, source); /// /// void wasm_v128_store8_lane (void *mem, v128_t vec, int i) /// v128.store8_lane memarg laneidx : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void StoreSelectedScalar(sbyte* address, Vector128 source, [ConstantExpected(Max = (byte)(15))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx16 /// /// void wasm_v128_store8_lane (void *mem, v128_t vec, int i) /// v128.store8_lane memarg laneidx : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void StoreSelectedScalar(byte* address, Vector128 source, [ConstantExpected(Max = (byte)(15))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx16 /// /// void wasm_v128_store16_lane (void *mem, v128_t vec, int i) /// v128.store16_lane memarg laneidx : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void StoreSelectedScalar(short* address, Vector128 source, [ConstantExpected(Max = (byte)(7))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx8 /// /// void wasm_v128_store16_lane (void *mem, v128_t vec, int i) /// v128.store16_lane memarg laneidx : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void StoreSelectedScalar(ushort* address, Vector128 source, [ConstantExpected(Max = (byte)(7))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx8 /// /// void wasm_v128_store32_lane (void *mem, v128_t vec, int i) /// v128.store32_lane memarg laneidx : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void StoreSelectedScalar(int* address, Vector128 source, [ConstantExpected(Max = (byte)(3))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx4 /// /// void wasm_v128_store32_lane (void *mem, v128_t vec, int i) /// v128.store32_lane memarg laneidx : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void StoreSelectedScalar(uint* address, Vector128 source, [ConstantExpected(Max = (byte)(3))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx4 /// /// void wasm_v128_store64_lane (void *mem, v128_t vec, int i) /// v128.store64_lane memarg laneidx : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void StoreSelectedScalar(long* address, Vector128 source, [ConstantExpected(Max = (byte)(1))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx2 /// /// void wasm_v128_store64_lane (void *mem, v128_t vec, int i) /// v128.store64_lane memarg laneidx : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void StoreSelectedScalar(ulong* address, Vector128 source, [ConstantExpected(Max = (byte)(1))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx2 /// /// void wasm_v128_store32_lane (void *mem, v128_t vec, int i) /// v128.store32_lane memarg laneidx : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void StoreSelectedScalar(float* address, Vector128 source, [ConstantExpected(Max = (byte)(3))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx4 /// /// void wasm_v128_store64_lane (void *mem, v128_t vec, int i) /// v128.store64_lane memarg laneidx : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void StoreSelectedScalar(double* address, Vector128 source, [ConstantExpected(Max = (byte)(1))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx2 /// /// void wasm_v128_store32_lane (void *mem, v128_t vec, int i) /// v128.store32_lane memarg laneidx : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void StoreSelectedScalar(nint* address, Vector128 source, [ConstantExpected(Max = (byte)(3))] byte index) => StoreSelectedScalar(address, source, index); /// /// void wasm_v128_store32_lane (void *mem, v128_t vec, int i) /// v128.store32_lane memarg laneidx : [i32 v128] -> [] /// - [Intrinsic] public static unsafe void StoreSelectedScalar(nuint* address, Vector128 source, [ConstantExpected(Max = (byte)(3))] byte index) => StoreSelectedScalar(address, source, index); /// /// v128_t wasm_i16x8_load8x8 (const void *mem) /// v128.load8x8_s memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadWideningVector128(sbyte* address) => LoadWideningVector128(address); /// /// v128_t wasm_u16x8_load8x8 (const void *mem) /// v128.load8x8_u memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadWideningVector128(byte* address) => LoadWideningVector128(address); /// /// v128_t wasm_i32x4_load16x4 (const void *mem) /// v128.load16x4_s memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadWideningVector128(short* address) => LoadWideningVector128(address); /// /// v128_t wasm_u32x4_load16x4 (const void *mem) /// v128.load16x4_u memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadWideningVector128(ushort* address) => LoadWideningVector128(address); /// /// v128_t wasm_i64x2_load32x2 (const void *mem) /// v128.load32x2_s memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadWideningVector128(int* address) => LoadWideningVector128(address); /// /// v128_t wasm_u64x2_load32x2 (const void *mem) /// v128.load32x2_u memarg : [i32] -> [v128] /// - [Intrinsic] public static unsafe Vector128 LoadWideningVector128(uint* address) => LoadWideningVector128(address); // Floating-point sign bit operations @@ -2491,26 +2116,22 @@ public abstract class PackedSimd /// v128_t wasm_f32x4_neg (v128_t a) /// f32x4.neg : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Negate(Vector128 value) => Negate(value); /// /// v128_t wasm_f64x2_neg (v128_t a) /// f64x2.neg : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Negate(Vector128 value) => Negate(value); /// /// v128_t wasm_f32x4_abs (v128_t a) /// f32x4.abs : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Abs(Vector128 value) => Abs(value); /// /// v128_t wasm_f64x2_abs (v128_t a) /// f64x2.abs : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Abs(Vector128 value) => Abs(value); // Floating-point min and max @@ -2519,52 +2140,44 @@ public abstract class PackedSimd /// v128_t wasm_f32x4_min (v128_t a, v128_t b) /// f32x4.min : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Min(Vector128 left, Vector128 right) => Min(left, right); /// /// v128_t wasm_f64x2_min (v128_t a, v128_t b) /// f64x2.min : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Min(Vector128 left, Vector128 right) => Min(left, right); /// /// v128_t wasm_f32x4_max (v128_t a, v128_t b) /// f32x4.max : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Max(Vector128 left, Vector128 right) => Max(left, right); /// /// v128_t wasm_f64x2_max (v128_t a, v128_t b) /// f64x2.max : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Max(Vector128 left, Vector128 right) => Max(left, right); /// /// v128_t wasm_f32x4_pmin (v128_t a, v128_t b) /// f32x4.pmin : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 PseudoMin(Vector128 left, Vector128 right) => PseudoMin(left, right); /// /// v128_t wasm_f64x2_pmin (v128_t a, v128_t b) /// f64x2.pmin : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 PseudoMin(Vector128 left, Vector128 right) => PseudoMin(left, right); /// /// v128_t wasm_f32x4_pmax (v128_t a, v128_t b) /// f32x4.pmax : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 PseudoMax(Vector128 left, Vector128 right) => PseudoMax(left, right); /// /// v128_t wasm_f64x2_pmax (v128_t a, v128_t b) /// f64x2.pmax : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 PseudoMax(Vector128 left, Vector128 right) => PseudoMax(left, right); // Floating-point arithmetic @@ -2573,117 +2186,99 @@ public abstract class PackedSimd /// v128_t wasm_f32x4_add (v128_t a, v128_t b) /// f32x4.add : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Add(Vector128 left, Vector128 right) => Add(left, right); /// /// v128_t wasm_f64x2_add (v128_t a, v128_t b) /// f64x2.add : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Add(Vector128 left, Vector128 right) => Add(left, right); /// /// v128_t wasm_f32x4_sub (v128_t a, v128_t b) /// f32x4.sub : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Subtract(Vector128 left, Vector128 right) => Subtract(left, right); /// /// v128_t wasm_f64x2_sub (v128_t a, v128_t b) /// f64x2.sub : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Subtract(Vector128 left, Vector128 right) => Subtract(left, right); /// /// v128_t wasm_f32x4_div (v128_t a, v128_t b) /// f32x4.div : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Divide(Vector128 left, Vector128 right) => Divide(left, right); /// /// v128_t wasm_f64x2_div (v128_t a, v128_t b) /// f64x2.div : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Divide(Vector128 left, Vector128 right) => Divide(left, right); /// /// v128_t wasm_f32x4_mul (v128_t a, v128_t b) /// f32x4.mul : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Multiply(Vector128 left, Vector128 right) => Multiply(left, right); /// /// v128_t wasm_f64x2_mul (v128_t a, v128_t b) /// f64x2.mul : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 Multiply(Vector128 left, Vector128 right) => Multiply(left, right); /// /// v128_t wasm_f32x4_sqrt (v128_t a) /// f32x4.sqrt : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Sqrt(Vector128 value) => Sqrt(value); /// /// v128_t wasm_f64x2_sqrt (v128_t a) /// f64x2.sqrt : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Sqrt(Vector128 value) => Sqrt(value); /// /// v128_t wasm_f32x4_ceil (v128_t a) /// f32x4.ceil : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Ceiling(Vector128 value) => Ceiling(value); /// /// v128_t wasm_f64x2_ceil (v128_t a) /// f64x2.ceil : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Ceiling(Vector128 value) => Ceiling(value); /// /// v128_t wasm_f32x4_floor (v128_t a) /// f32x4.floor : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Floor(Vector128 value) => Floor(value); /// /// v128_t wasm_f64x2_floor (v128_t a) /// f64x2.floor : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Floor(Vector128 value) => Floor(value); /// /// v128_t wasm_f32x4_trunc (v128_t a) /// f32x4.trunc : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Truncate(Vector128 value) => Truncate(value); /// /// v128_t wasm_f64x2_trunc (v128_t a) /// f64x2.trunc : [v128] -> [v128] /// - [Intrinsic] public static Vector128 Truncate(Vector128 value) => Truncate(value); /// /// v128_t wasm_f32x4_nearest (v128_t a) /// f32x4.nearest : [v128] -> [v128] /// - [Intrinsic] public static Vector128 RoundToNearest(Vector128 value) => RoundToNearest(value); /// /// v128_t wasm_f64x2_nearest (v128_t a) /// f64x2.nearest : [v128] -> [v128] /// - [Intrinsic] public static Vector128 RoundToNearest(Vector128 value) => RoundToNearest(value); // Conversions @@ -2692,240 +2287,202 @@ public abstract class PackedSimd /// v128_t wasm_f32x4_convert_i32x4 (v128_t a) /// f32x4.convert_i32x4_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertToSingle(Vector128 value) => ConvertToSingle(value); /// /// v128_t wasm_f32x4_convert_u32x4 (v128_t a) /// f32x4.convert_i32x4_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertToSingle(Vector128 value) => ConvertToSingle(value); /// /// v128_t wasm_f32x4_demote_f64x2_zero (v128_t a) /// f32x4.demote_f64x2_zero : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertToSingle(Vector128 value) => ConvertToSingle(value); /// /// v128_t wasm_f64x2_convert_low_i32x4 (v128_t a) /// f64x2.convert_low_i32x4_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertToDoubleLower(Vector128 value) => ConvertToDoubleLower(value); /// /// v128_t wasm_f64x2_convert_low_u32x4 (v128_t a) /// f64x2.convert_low_i32x4_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertToDoubleLower(Vector128 value) => ConvertToDoubleLower(value); /// /// v128_t wasm_f64x2_promote_low_f32x4 (v128_t a) /// f64x2.promote_low_f32x4 : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertToDoubleLower(Vector128 value) => ConvertToDoubleLower(value); /// /// v128_t wasm_i32x4_trunc_sat_f32x4 (v128_t a) /// i32x4.trunc_sat_f32x4_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertToInt32Saturate(Vector128 value) => ConvertToInt32Saturate(value); /// /// v128_t wasm_u32x4_trunc_sat_f32x4 (v128_t a) /// i32x4.trunc_sat_f32x4_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertToUInt32Saturate(Vector128 value) => ConvertToUInt32Saturate(value); /// /// v128_t wasm_i32x4_trunc_sat_f64x2_zero (v128_t a) /// i32x4.trunc_sat_f64x2_s_zero : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertToInt32Saturate(Vector128 value) => ConvertToInt32Saturate(value); /// /// v128_t wasm_u32x4_trunc_sat_f64x2_zero (v128_t a) /// i32x4.trunc_sat_f64x2_u_zero : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertToUInt32Saturate(Vector128 value) => ConvertToUInt32Saturate(value); /// /// v128_t wasm_i8x16_narrow_i16x8 (v128_t a, v128_t b) /// i8x16.narrow_i16x8_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertNarrowingSaturateSigned(Vector128 lower, Vector128 upper) => ConvertNarrowingSaturateSigned(lower, upper); /// /// v128_t wasm_i16x8_narrow_i32x4 (v128_t a, v128_t b) /// i16x8.narrow_i32x4_s : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertNarrowingSaturateSigned(Vector128 lower, Vector128 upper) => ConvertNarrowingSaturateSigned(lower, upper); /// /// v128_t wasm_u8x16_narrow_i16x8 (v128_t a, v128_t b) /// i8x16.narrow_i16x8_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertNarrowingSaturateUnsigned(Vector128 lower, Vector128 upper) => ConvertNarrowingSaturateUnsigned(lower, upper); /// /// v128_t wasm_u16x8_narrow_i32x4 (v128_t a, v128_t b) /// i16x8.narrow_i32x4_u : [v128 v128] -> [v128] /// - [Intrinsic] public static Vector128 ConvertNarrowingSaturateUnsigned(Vector128 lower, Vector128 upper) => ConvertNarrowingSaturateUnsigned(lower, upper); /// /// v128_t wasm_i16x8_extend_low_i8x16 (v128_t a) /// i16x8.extend_low_i8x16_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 SignExtendWideningLower(Vector128 value) => SignExtendWideningLower(value); /// /// v128_t wasm_i16x8_extend_low_i8x16 (v128_t a) /// i16x8.extend_low_i8x16_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 SignExtendWideningLower(Vector128 value) => SignExtendWideningLower(value); /// /// v128_t wasm_i32x4_extend_low_i16x8 (v128_t a) /// i32x4.extend_low_i16x8_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 SignExtendWideningLower(Vector128 value) => SignExtendWideningLower(value); /// /// v128_t wasm_i32x4_extend_low_i16x8 (v128_t a) /// i32x4.extend_low_i16x8_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 SignExtendWideningLower(Vector128 value) => SignExtendWideningLower(value); /// /// v128_t wasm_i64x2_extend_low_i32x4 (v128_t a) /// i64x2.extend_low_i32x4_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 SignExtendWideningLower(Vector128 value) => SignExtendWideningLower(value); /// /// v128_t wasm_i64x2_extend_low_i32x4 (v128_t a) /// i64x2.extend_low_i32x4_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 SignExtendWideningLower(Vector128 value) => SignExtendWideningLower(value); /// /// v128_t wasm_i16x8_extend_high_i8x16 (v128_t a) /// i16x8.extend_high_i8x16_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); /// /// v128_t wasm_i16x8_extend_high_i8x16 (v128_t a) /// i16x8.extend_high_i8x16_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); /// /// v128_t wasm_i32x4_extend_high_i16x8 (v128_t a) /// i32x4.extend_high_i16x8_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); /// /// v128_t wasm_i32x4_extend_high_i16x8 (v128_t a) /// i32x4.extend_high_i16x8_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); /// /// v128_t wasm_i64x2_extend_high_i32x4 (v128_t a) /// i64x2.extend_high_i32x4_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); /// /// v128_t wasm_i64x2_extend_high_i32x4 (v128_t a) /// i64x2.extend_high_i32x4_s : [v128] -> [v128] /// - [Intrinsic] public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); /// /// v128_t wasm_u16x8_extend_low_u8x16 (v128_t a) /// i16x8.extend_low_i8x16_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ZeroExtendWideningLower(Vector128 value) => ZeroExtendWideningLower(value); /// /// v128_t wasm_u16x8_extend_low_u8x16 (v128_t a) /// i16x8.extend_low_i8x16_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ZeroExtendWideningLower(Vector128 value) => ZeroExtendWideningLower(value); /// /// v128_t wasm_u32x4_extend_low_u16x8 (v128_t a) /// i32x4.extend_low_i16x8_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ZeroExtendWideningLower(Vector128 value) => ZeroExtendWideningLower(value); /// /// v128_t wasm_u32x4_extend_low_u16x8 (v128_t a) /// i32x4.extend_low_i16x8_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ZeroExtendWideningLower(Vector128 value) => ZeroExtendWideningLower(value); /// /// v128_t wasm_u64x2_extend_low_u32x4 (v128_t a) /// i64x2.extend_low_i32x4_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ZeroExtendWideningLower(Vector128 value) => ZeroExtendWideningLower(value); /// /// v128_t wasm_u64x2_extend_low_u32x4 (v128_t a) /// i64x2.extend_low_i32x4_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ZeroExtendWideningLower(Vector128 value) => ZeroExtendWideningLower(value); /// /// v128_t wasm_u16x8_extend_high_u8x16 (v128_t a) /// i16x8.extend_high_i8x16_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); /// /// v128_t wasm_u16x8_extend_high_u8x16 (v128_t a) /// i16x8.extend_high_i8x16_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); /// /// v128_t wasm_u32x4_extend_high_u16x8 (v128_t a) /// i32x4.extend_high_i16x8_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); /// /// v128_t wasm_u32x4_extend_high_u16x8 (v128_t a) /// i32x4.extend_high_i16x8_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); /// /// v128_t wasm_u64x2_extend_high_u32x4 (v128_t a) /// i64x2.extend_high_i32x4_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); /// /// v128_t wasm_u64x2_extend_high_u32x4 (v128_t a) /// i64x2.extend_high_i32x4_u : [v128] -> [v128] /// - [Intrinsic] public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/RelaxedSimd.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/RelaxedSimd.PlatformNotSupported.cs new file mode 100644 index 00000000000000..f3f640a3926d47 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/RelaxedSimd.PlatformNotSupported.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; + +namespace System.Runtime.Intrinsics.Wasm +{ + [CLSCompliant(false)] + public abstract class RelaxedSimd + { + /// Gets a value that indicates whether the APIs in this class are supported. + /// if the APIs are supported; otherwise, . + /// A value of indicates that the APIs will throw . + public static bool IsSupported { [Intrinsic] get { return false; } } + + public static Vector128 SwizzleNative(Vector128 vector, Vector128 indices) { throw new PlatformNotSupportedException(); } + public static Vector128 SwizzleNative(Vector128 vector, Vector128 indices) { throw new PlatformNotSupportedException(); } + + public static Vector128 ConvertToInt32Native(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ConvertToUInt32Native(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ConvertToInt32Native(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ConvertToUInt32Native(Vector128 value) { throw new PlatformNotSupportedException(); } + + public static Vector128 MultiplyAddEstimate(Vector128 left, Vector128 right, Vector128 addend) { throw new PlatformNotSupportedException(); } + public static Vector128 MultiplyAddEstimate(Vector128 left, Vector128 right, Vector128 addend) { throw new PlatformNotSupportedException(); } + + public static Vector128 MultiplyAddNegatedEstimate(Vector128 left, Vector128 right, Vector128 addend) { throw new PlatformNotSupportedException(); } + public static Vector128 MultiplyAddNegatedEstimate(Vector128 left, Vector128 right, Vector128 addend) { throw new PlatformNotSupportedException(); } + + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) { throw new PlatformNotSupportedException(); } + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) { throw new PlatformNotSupportedException(); } + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) { throw new PlatformNotSupportedException(); } + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) { throw new PlatformNotSupportedException(); } + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) { throw new PlatformNotSupportedException(); } + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) { throw new PlatformNotSupportedException(); } + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) { throw new PlatformNotSupportedException(); } + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) { throw new PlatformNotSupportedException(); } + + public static Vector128 MinNative(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 MaxNative(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 MinNative(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 MaxNative(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + public static Vector128 MultiplyRoundedQ15Native(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + public static Vector128 DotProductNative(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 DotProductAddNative(Vector128 left, Vector128 right, Vector128 accumulator) { throw new PlatformNotSupportedException(); } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/RelaxedSimd.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/RelaxedSimd.cs new file mode 100644 index 00000000000000..06e1598f895a92 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/RelaxedSimd.cs @@ -0,0 +1,199 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; + +namespace System.Runtime.Intrinsics.Wasm +{ + /// Provides access to the WebAssembly relaxed SIMD instructions via intrinsics. + /// + /// + /// Operations exposed on this class behave "relaxedly": for inputs outside a well-defined range + /// the result is implementation-defined and may differ between WebAssembly engines and host + /// architectures. Callers that require deterministic semantics across engines should use the + /// corresponding operation (where available) instead. + /// + /// + /// All operations exposed by this class require the WebAssembly engine to support the + /// relaxed SIMD WebAssembly proposal. + /// + /// + [Intrinsic] + [CLSCompliant(false)] + public abstract class RelaxedSimd + { + /// Gets a value that indicates whether the APIs in this class are supported. + /// if the APIs are supported; otherwise, . + /// A value of indicates that the APIs will throw . + public static bool IsSupported { get { return IsSupported; } } + + /// Swizzles the elements in a vector using the specified indices. + /// The vector to swizzle. + /// The indices used to select elements from . + /// The swizzled vector. + /// + /// This method maps to the i8x16.relaxed_swizzle instruction. For indices outside + /// the range [0, 16), the result is implementation-defined. Use the corresponding + /// PackedSimd.Swizzle overload when deterministic handling of out-of-range indices is required. + /// + public static Vector128 SwizzleNative(Vector128 vector, Vector128 indices) => SwizzleNative(vector, indices); + /// + public static Vector128 SwizzleNative(Vector128 vector, Vector128 indices) => SwizzleNative(vector, indices); + + /// Converts a vector of single-precision floating-point values to a vector of signed integers using native truncation. + /// The vector to convert. + /// The converted vector. + /// + /// This method maps to the i32x4.relaxed_trunc_f32x4_s instruction. The result for + /// NaN or out-of-range inputs is implementation-defined. Use + /// for deterministic saturation. + /// + public static Vector128 ConvertToInt32Native(Vector128 value) => ConvertToInt32Native(value); + /// Converts a vector of single-precision floating-point values to a vector of unsigned integers using native truncation. + /// The vector to convert. + /// The converted vector. + /// + /// This method maps to the i32x4.relaxed_trunc_f32x4_u instruction. The result for + /// NaN or out-of-range inputs is implementation-defined. Use + /// for deterministic saturation. + /// + public static Vector128 ConvertToUInt32Native(Vector128 value) => ConvertToUInt32Native(value); + /// Converts a vector of double-precision floating-point values to a vector of signed integers using native truncation. + /// The vector to convert. + /// The converted vector, with the upper two elements initialized to zero. + /// + /// This method maps to the i32x4.relaxed_trunc_f64x2_s_zero instruction. The result + /// for NaN or out-of-range inputs is implementation-defined. Use + /// for deterministic saturation. + /// + public static Vector128 ConvertToInt32Native(Vector128 value) => ConvertToInt32Native(value); + /// Converts a vector of double-precision floating-point values to a vector of unsigned integers using native truncation. + /// The vector to convert. + /// The converted vector, with the upper two elements initialized to zero. + /// + /// This method maps to the i32x4.relaxed_trunc_f64x2_u_zero instruction. The result + /// for NaN or out-of-range inputs is implementation-defined. Use + /// for deterministic saturation. + /// + public static Vector128 ConvertToUInt32Native(Vector128 value) => ConvertToUInt32Native(value); + + /// Computes an implementation-dependent estimate of the product of two vectors added to a third vector. + /// The first vector to multiply. + /// The second vector to multiply. + /// The vector to add to the product. + /// The estimated multiply-add result. + /// + /// This method maps to the corresponding relaxed_madd instruction. Whether the + /// product is rounded before the addition, and whether the operation is fused, is + /// implementation-defined. + /// + public static Vector128 MultiplyAddEstimate(Vector128 left, Vector128 right, Vector128 addend) => MultiplyAddEstimate(left, right, addend); + /// + public static Vector128 MultiplyAddEstimate(Vector128 left, Vector128 right, Vector128 addend) => MultiplyAddEstimate(left, right, addend); + + /// Computes an implementation-dependent estimate of the negated product of two vectors added to a third vector. + /// The first vector to multiply. + /// The second vector to multiply. + /// The vector to add to the negated product. + /// The estimated negated multiply-add result. + /// + /// This method maps to the corresponding relaxed_nmadd instruction. Whether the + /// product is rounded before the addition, and whether the operation is fused, is + /// implementation-defined. + /// + public static Vector128 MultiplyAddNegatedEstimate(Vector128 left, Vector128 right, Vector128 addend) => MultiplyAddNegatedEstimate(left, right, addend); + /// + public static Vector128 MultiplyAddNegatedEstimate(Vector128 left, Vector128 right, Vector128 addend) => MultiplyAddNegatedEstimate(left, right, addend); + + /// Selects elements from two vectors using the specified mask. + /// The vector selected when a mask element is all bits set. + /// The vector selected when a mask element is zero. + /// The mask used to select elements. + /// A vector containing the selected elements. + /// + /// This method maps to the corresponding relaxed_laneselect instruction. The result + /// is implementation-defined for mask elements that are neither all bits set nor zero. Use + /// + /// when deterministic bitwise selection is required. + /// + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) => LaneSelectNative(left, right, mask); + /// + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) => LaneSelectNative(left, right, mask); + /// + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) => LaneSelectNative(left, right, mask); + /// + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) => LaneSelectNative(left, right, mask); + /// + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) => LaneSelectNative(left, right, mask); + /// + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) => LaneSelectNative(left, right, mask); + /// + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) => LaneSelectNative(left, right, mask); + /// + public static Vector128 LaneSelectNative(Vector128 left, Vector128 right, Vector128 mask) => LaneSelectNative(left, right, mask); + + /// Computes the minimum of each pair of elements in two vectors. + /// The first vector. + /// The second vector. + /// A vector containing the minimum values. + /// + /// This method maps to the corresponding relaxed_min instruction. NaN handling and + /// the sign of a zero result are implementation-defined. Use PackedSimd.Min for + /// IEEE-compliant behavior or PackedSimd.PseudoMin for pseudo-minimum behavior. + /// + public static Vector128 MinNative(Vector128 left, Vector128 right) => MinNative(left, right); + /// Computes the maximum of each pair of elements in two vectors. + /// The first vector. + /// The second vector. + /// A vector containing the maximum values. + /// + /// This method maps to the corresponding relaxed_max instruction. NaN handling and + /// the sign of a zero result are implementation-defined. Use PackedSimd.Max for + /// IEEE-compliant behavior or PackedSimd.PseudoMax for pseudo-maximum behavior. + /// + public static Vector128 MaxNative(Vector128 left, Vector128 right) => MaxNative(left, right); + /// + public static Vector128 MinNative(Vector128 left, Vector128 right) => MinNative(left, right); + /// + public static Vector128 MaxNative(Vector128 left, Vector128 right) => MaxNative(left, right); + + /// Multiplies corresponding signed 16-bit fixed-point elements and returns their rounded high halves. + /// The first vector to multiply. + /// The second vector to multiply. + /// The rounded fixed-point products. + /// + /// This method maps to the i16x8.relaxed_q15mulr_s instruction. The result of + /// multiplying by is + /// implementation-defined. Use + /// + /// when deterministic saturation is required. + /// + public static Vector128 MultiplyRoundedQ15Native(Vector128 left, Vector128 right) => MultiplyRoundedQ15Native(left, right); + + /// Multiplies adjacent signed and unsigned byte elements and sums each pair into a signed 16-bit element. + /// The vector containing signed byte elements. + /// The vector containing unsigned 7-bit elements. + /// The pairwise dot products. + /// + /// This method maps to the i16x8.relaxed_dot_i8x16_i7x16_s instruction. If an element + /// in has its high bit set, whether it is interpreted as signed or + /// unsigned is implementation-defined. Whether the pairwise sum saturates on overflow is + /// also implementation-defined. + /// + public static Vector128 DotProductNative(Vector128 left, Vector128 right) => DotProductNative(left, right); + + /// Multiplies groups of four signed and unsigned byte elements and adds each sum to a signed 32-bit accumulator. + /// The vector containing signed byte elements. + /// The vector containing unsigned 7-bit elements. + /// The vector added to the dot products. + /// The accumulated dot products. + /// + /// This method maps to the i32x4.relaxed_dot_i8x16_i7x16_add_s instruction. If an + /// element in has its high bit set, whether it is interpreted as + /// signed or unsigned is implementation-defined. Whether the group sum saturates on + /// overflow is also implementation-defined. + /// + public static Vector128 DotProductAddNative(Vector128 left, Vector128 right, Vector128 accumulator) => DotProductAddNative(left, right, accumulator); + } +} diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 11653a06b37825..50b9c20b3e971c 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -11984,4 +11984,35 @@ public abstract partial class PackedSimd public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw null; } public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw null; } } + [System.CLSCompliantAttribute(false)] + public abstract partial class RelaxedSimd + { + protected RelaxedSimd() { } + public static bool IsSupported { get { throw null; } } + public static System.Runtime.Intrinsics.Vector128 ConvertToInt32Native(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ConvertToInt32Native(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector128 value) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DotProductAddNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 accumulator) { throw null; } + public static System.Runtime.Intrinsics.Vector128 DotProductNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 LaneSelectNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 mask) { throw null; } + public static System.Runtime.Intrinsics.Vector128 LaneSelectNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 mask) { throw null; } + public static System.Runtime.Intrinsics.Vector128 LaneSelectNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 mask) { throw null; } + public static System.Runtime.Intrinsics.Vector128 LaneSelectNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 mask) { throw null; } + public static System.Runtime.Intrinsics.Vector128 LaneSelectNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 mask) { throw null; } + public static System.Runtime.Intrinsics.Vector128 LaneSelectNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 mask) { throw null; } + public static System.Runtime.Intrinsics.Vector128 LaneSelectNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 mask) { throw null; } + public static System.Runtime.Intrinsics.Vector128 LaneSelectNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 mask) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MaxNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MaxNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MinNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MinNative(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MultiplyAddEstimate(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 addend) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MultiplyAddEstimate(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 addend) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MultiplyAddNegatedEstimate(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 addend) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MultiplyAddNegatedEstimate(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right, System.Runtime.Intrinsics.Vector128 addend) { throw null; } + public static System.Runtime.Intrinsics.Vector128 MultiplyRoundedQ15Native(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SwizzleNative(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector128 SwizzleNative(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } + } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj b/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj index 5d98f157e174a3..e12121e625bb82 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj +++ b/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj @@ -5,6 +5,8 @@ true true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-unix;$(NetCoreAppCurrent)-browser + true + false $(Features.Replace('nullablePublicOnly', '') @@ -14,6 +16,7 @@ + diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Wasm/RelaxedSimdTests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Wasm/RelaxedSimdTests.cs new file mode 100644 index 00000000000000..ec39ca965fa52a --- /dev/null +++ b/src/libraries/System.Runtime.Intrinsics/tests/Wasm/RelaxedSimdTests.cs @@ -0,0 +1,136 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Reflection; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Wasm; +using Xunit; + +namespace System.Runtime.Intrinsics.Wasm.Tests +{ + [PlatformSpecific(TestPlatforms.Browser)] + public sealed class RelaxedSimdTests + { + public static bool IsNotSupported => !RelaxedSimd.IsSupported; + + [Fact] + public void RelaxedSimdIsSupportedReflects() + { + MethodInfo methodInfo = typeof(RelaxedSimd).GetMethod("get_IsSupported"); + Assert.NotNull(methodInfo); + Assert.Equal(RelaxedSimd.IsSupported, methodInfo.Invoke(null, null)); + } + + [ConditionalFact(typeof(RelaxedSimdTests), nameof(IsNotSupported))] + public void UnsupportedMethodThrowsPlatformNotSupportedException() + { + Assert.Throws( + () => RelaxedSimd.ConvertToInt32Native(Vector128.Create(1.0f))); + } + + [ConditionalFact(typeof(RelaxedSimd), nameof(RelaxedSimd.IsSupported))] + public void ConvertToIntegerNativeInRangeMatchesExpected() + { + Assert.Equal( + Vector128.Create(1, -2, 3, -4), + RelaxedSimd.ConvertToInt32Native(Vector128.Create(1.75f, -2.25f, 3.0f, -4.99f))); + Assert.Equal( + Vector128.Create(5, -6, 0, 0), + RelaxedSimd.ConvertToInt32Native(Vector128.Create(5.75, -6.25))); + Assert.Equal( + Vector128.Create(1u, 2u, 3u, 4u), + RelaxedSimd.ConvertToUInt32Native(Vector128.Create(1.75f, 2.25f, 3.0f, 4.99f))); + Assert.Equal( + Vector128.Create(5u, 6u, 0u, 0u), + RelaxedSimd.ConvertToUInt32Native(Vector128.Create(5.75, 6.25))); + } + + [ConditionalFact(typeof(RelaxedSimd), nameof(RelaxedSimd.IsSupported))] + public void DotProductNativeByteSByteMatchesScalar() + { + // Per the finished spec, `a` is signed and `b` is unsigned-7-bit. When every lane + // of `b` is in [0, 127] every implementation must match a straightforward + // pairwise (sbyte, byte) -> int16 multiply-add. + var s = Vector128.Create((sbyte)-1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15, 16); + var u = Vector128.Create((byte)2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3); + + Vector128 actual = RelaxedSimd.DotProductNative(s, u); + + for (int i = 0; i < 8; i++) + { + short expected = (short)(s[2 * i] * u[2 * i] + s[2 * i + 1] * u[2 * i + 1]); + Assert.Equal(expected, actual[i]); + } + } + + [ConditionalFact(typeof(RelaxedSimd), nameof(RelaxedSimd.IsSupported))] + public void DotProductAddNativeByteSByteMatchesScalar() + { + var s = Vector128.Create((sbyte)-1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15, 16); + var u = Vector128.Create((byte)2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3); + var acc = Vector128.Create(100, 200, 300, 400); + + Vector128 actual = RelaxedSimd.DotProductAddNative(s, u, acc); + + for (int i = 0; i < 4; i++) + { + int expected = acc[i]; + for (int j = 0; j < 4; j++) + expected += s[4 * i + j] * u[4 * i + j]; + Assert.Equal(expected, actual[i]); + } + } + + [ConditionalFact(typeof(RelaxedSimd), nameof(RelaxedSimd.IsSupported))] + public void MultiplyAddFloatMatchesScalarApproximately() + { + // Relaxed FMA may or may not round the intermediate product; verify the result is + // within a small relative tolerance of the unfused result. float.Epsilon is a + // subnormal (~1.4e-45) and is not a meaningful ULP scale for this comparison, so we + // use a plain relative epsilon calibrated for single precision. + var a = Vector128.Create(1.5f, 2.25f, -3.125f, 4.0f); + var b = Vector128.Create(2.0f, -1.5f, 0.5f, 6.25f); + var c = Vector128.Create(0.5f, 1.0f, -0.25f, -2.0f); + + Vector128 actual = RelaxedSimd.MultiplyAddEstimate(a, b, c); + Vector128 unfused = (a * b) + c; + + const float RelativeTolerance = 1e-5f; + for (int i = 0; i < 4; i++) + { + float tolerance = Math.Max(Math.Abs(unfused[i]), 1.0f) * RelativeTolerance; + Assert.True(Math.Abs(actual[i] - unfused[i]) <= tolerance, + $"lane {i}: relaxed FMA {actual[i]} differs from unfused {unfused[i]} by more than {tolerance}"); + } + } + + [ConditionalFact(typeof(RelaxedSimd), nameof(RelaxedSimd.IsSupported))] + public void LaneSelectNativeAllOnesAllZerosBehavesLikeConditionalSelect() + { + // For mask lanes that are all-ones or all-zeros the relaxed lane select must match + // the deterministic semantics. + var left = Vector128.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + var right = Vector128.Create((byte)17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + var mask = Vector128.Create((byte)0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00); + + Vector128 actual = RelaxedSimd.LaneSelectNative(left, right, mask); + Vector128 expected = Vector128.ConditionalSelect(mask, left, right); + + Assert.Equal(expected, actual); + } + + [ConditionalFact(typeof(RelaxedSimd), nameof(RelaxedSimd.IsSupported))] + public void SwizzleNativeInRangeMatchesVector128Shuffle() + { + // For index lanes in [0, 16) the relaxed swizzle must agree with Vector128.Shuffle. + var v = Vector128.Create((byte)10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160); + var idx = Vector128.Create((byte)15, 0, 14, 1, 13, 2, 12, 3, 11, 4, 10, 5, 9, 6, 8, 7); + + Vector128 actual = RelaxedSimd.SwizzleNative(v, idx); + Vector128 expected = Vector128.Shuffle(v, idx); + + Assert.Equal(expected, actual); + } + } +} diff --git a/src/mono/browser/browser.proj b/src/mono/browser/browser.proj index 710a36801a553b..3ba314bbcc06e9 100644 --- a/src/mono/browser/browser.proj +++ b/src/mono/browser/browser.proj @@ -21,6 +21,7 @@ true false true + false true 2147483648 true @@ -247,6 +248,9 @@ + + + <_EmccLinkFlags Include="--profiling-funcs" /> @@ -277,6 +281,7 @@ { "identity": "WasmNativeStrip", "defaultValueInRuntimePack": "$(WasmNativeStrip)" }, { "identity": "WasmSingleFileBundle", "defaultValueInRuntimePack": "$(WasmSingleFileBundle)" }, { "identity": "WasmEnableSIMD", "defaultValueInRuntimePack": "$(WasmEnableSIMD)" }, + { "identity": "WasmEnableRelaxedSimd", "defaultValueInRuntimePack": "$(WasmEnableRelaxedSimd)" }, { "identity": "WasmEnableExceptionHandling", "defaultValueInRuntimePack": "$(WasmEnableExceptionHandling)" }, { "identity": "EnableDiagnostics", "defaultValueInRuntimePack": "$(EnableDiagnostics)" }, { "identity": "WasmProfilers", "defaultValueInRuntimePack": "$(WasmProfilers)" }, @@ -329,6 +334,7 @@ $(CMakeConfigurationLinkFlags) -s EXPORT_ES6=1 -lexports.js $(CMakeConfigurationLinkFlags) -msimd128 + $(CMakeConfigurationLinkFlags) -mrelaxed-simd $(CMakeConfigurationLinkFlags) -Wno-pthreads-mem-growth $(CMakeConfigurationLinkFlags) --emit-symbol-map $(CMakeConfigurationLinkFlags) -fwasm-exceptions -sWASM_LEGACY_EXCEPTIONS=0 @@ -345,7 +351,8 @@ $(CMakeBuildRuntimeConfigureCmd) -DMONO_OBJ_INCLUDES="$(MonoObjDir.TrimEnd('\/').Replace('\','/'))" $(CMakeBuildRuntimeConfigureCmd) -DMONO_ARTIFACTS_DIR="$(MonoArtifactsPath.TrimEnd('\/').Replace('\','/'))" $(CMakeBuildRuntimeConfigureCmd) -DNATIVE_BIN_DIR="$(NativeBinDir.TrimEnd('\/').Replace('\','/'))" - $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_COMPILE_OPTIONS="-msimd128" -DCONFIGURATION_INTERPSIMDTABLES_LIB="simd" + $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_COMPILE_OPTIONS="-msimd128;-mrelaxed-simd" -DCONFIGURATION_INTERPSIMDTABLES_LIB="relaxed-simd" + $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_COMPILE_OPTIONS="-msimd128" -DCONFIGURATION_INTERPSIMDTABLES_LIB="simd" $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_INTERPSIMDTABLES_LIB="nosimd" $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_EH_LIB="eh-wasm" diff --git a/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets b/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets index a277500ae12aa9..975004eee76782 100644 --- a/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets +++ b/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets @@ -34,9 +34,12 @@ <_CoreCLRInvalidSIMD Condition="'$(WasmEnableSIMD)' != '' and '$(WasmEnableSIMD)' != 'true'">true true true + false emcc <_WasmDefaultFlags>-fwasm-exceptions -sWASM_LEGACY_EXCEPTIONS=0 -msimd128 + <_WasmDefaultFlags Condition="'$(WasmEnableRelaxedSimd)' == 'true'">$(_WasmDefaultFlags) -mrelaxed-simd + $(PublishReadyToRunCrossgen2ExtraArgs);--instruction-set:relaxed-simd Build Publish @@ -67,6 +70,12 @@ <_ExeExt Condition="$([MSBuild]::IsOSPlatform('windows'))">.exe + + + + $(PublishReadyToRunCrossgen2ExtraArgs);--codegenopt:JitWasmNyiToR2RUnsupported=1;--codegenopt:JitWasmSimdNyiToR2RUnsupported=1 + $(PublishReadyToRunCrossgen2ExtraArgs);--instruction-set:relaxed-simd + + + + <_WasmNativeWorkloadNeeded Condition=" '$(WasmEnableSIMD)' == 'false' or + '$(WasmEnableRelaxedSimd)' == 'true' or '$(WasmEnableExceptionHandling)' == 'false' or '$(InvariantTimezone)' == 'true' or '$(WasmNativeStrip)' == 'false' or diff --git a/src/mono/wasi/README.md b/src/mono/wasi/README.md index 45f1d2fb5ee981..cd2c309e623992 100644 --- a/src/mono/wasi/README.md +++ b/src/mono/wasi/README.md @@ -55,6 +55,7 @@ The following MSBuild properties will trigger a relinking during the WASI build - **`EnableDiagnostics`** - `/p:EnableDiagnostics=true` - Enables or disables diagnostic features in the native runtime. - **`WasmProfilers`** - `/p:WasmProfilers=...` - Changes profiler configuration in the native runtime. - **`WasmEnableSIMD`** - `/p:WasmEnableSIMD=true` - Enables or disables SIMD instruction support. +- **`WasmEnableRelaxedSimd`** - `/p:WasmEnableRelaxedSimd=true` - Enables relaxed SIMD instruction support and requires `WasmEnableSIMD=true`. - **`WasiBuildArgs`** - Any change to `/p:WasiBuildArgs=...` (custom build flags or feature toggles) can trigger a relink. - **Configuration/Target Architecture** - Changing `/p:Configuration=Debug|Release` or `/p:RuntimeIdentifier=wasi-wasm`, etc., may require relinking. diff --git a/src/mono/wasi/build/WasiApp.targets b/src/mono/wasi/build/WasiApp.targets index da14aeaaf6b5db..7e8a2b61c71538 100644 --- a/src/mono/wasi/build/WasiApp.targets +++ b/src/mono/wasi/build/WasiApp.targets @@ -57,6 +57,8 @@ <_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' != 'false' and '$(_WasiIntrinsicsSubstitutionsDir)' != ''">$(_ExtraTrimmerArgs) --substitutions "$(_WasiIntrinsicsSubstitutionsDir)ILLink.Substitutions.WasmIntrinsics.xml" <_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' == 'false' and '$(_WasiIntrinsicsSubstitutionsDir)' != ''">$(_ExtraTrimmerArgs) --substitutions "$(_WasiIntrinsicsSubstitutionsDir)ILLink.Substitutions.NoWasmIntrinsics.xml" + <_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' != 'false' and '$(WasmEnableRelaxedSimd)' == 'true' and '$(_WasiIntrinsicsSubstitutionsDir)' != ''">$(_ExtraTrimmerArgs) --substitutions "$(_WasiIntrinsicsSubstitutionsDir)ILLink.Substitutions.WasmRelaxedSimd.xml" + <_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' != 'false' and '$(WasmEnableRelaxedSimd)' != 'true' and '$(_WasiIntrinsicsSubstitutionsDir)' != ''">$(_ExtraTrimmerArgs) --substitutions "$(_WasiIntrinsicsSubstitutionsDir)ILLink.Substitutions.NoWasmRelaxedSimd.xml" false @@ -259,6 +261,7 @@ <_WasiClangCommonFlags Include="-msimd128" Condition="'$(WasmEnableSIMD)' == 'true'" /> + <_WasiClangCommonFlags Include="-mrelaxed-simd" Condition="'$(WasmEnableSIMD)' == 'true' and '$(WasmEnableRelaxedSimd)' == 'true'" /> <_WasmCommonCFlags Include="-DGEN_PINVOKE=1" /> <_WasmCommonCFlags Condition="'$(_WasmShouldAOT)' == 'true'" Include="-DENABLE_AOT=1" /> @@ -369,10 +372,12 @@ <_WasmEHLibToExclude Condition="'$(WasmEnableExceptionHandling)' != 'true'">libmono-wasm-eh-wasm.a - <_WasmSIMDLib Condition="'$(WasmEnableSIMD)' == 'true'">libmono-wasm-simd.a + <_WasmSIMDLib Condition="'$(WasmEnableSIMD)' == 'true' and '$(WasmEnableRelaxedSimd)' == 'true'">libmono-wasm-relaxed-simd.a + <_WasmSIMDLib Condition="'$(WasmEnableSIMD)' == 'true' and '$(WasmEnableRelaxedSimd)' != 'true'">libmono-wasm-simd.a <_WasmSIMDLib Condition="'$(WasmEnableSIMD)' != 'true'">libmono-wasm-nosimd.a - <_WasmSIMDLibToExclude Condition="'$(WasmEnableSIMD)' != 'true'">libmono-wasm-simd.a - <_WasmSIMDLibToExclude Condition="'$(WasmEnableSIMD)' == 'true'">libmono-wasm-nosimd.a + <_WasmSIMDLibToExclude Condition="'$(WasmEnableSIMD)' != 'true'">$(MicrosoftNetCoreAppRuntimePackRidNativeDir)libmono-wasm-simd.a;$(MicrosoftNetCoreAppRuntimePackRidNativeDir)libmono-wasm-relaxed-simd.a + <_WasmSIMDLibToExclude Condition="'$(WasmEnableSIMD)' == 'true' and '$(WasmEnableRelaxedSimd)' != 'true'">$(MicrosoftNetCoreAppRuntimePackRidNativeDir)libmono-wasm-nosimd.a;$(MicrosoftNetCoreAppRuntimePackRidNativeDir)libmono-wasm-relaxed-simd.a + <_WasmSIMDLibToExclude Condition="'$(WasmEnableSIMD)' == 'true' and '$(WasmEnableRelaxedSimd)' == 'true'">$(MicrosoftNetCoreAppRuntimePackRidNativeDir)libmono-wasm-nosimd.a;$(MicrosoftNetCoreAppRuntimePackRidNativeDir)libmono-wasm-simd.a @@ -403,7 +408,7 @@ <_WasmNativeFileForLinking Condition="'$(_WasmEHLib)' != ''" Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(_WasmEHLib)" /> <_WasmNativeFileForLinking Condition="'$(_WasmSIMDLib)' != ''" Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(_WasmSIMDLib)" /> <_WasmNativeFileForLinking Remove="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(_WasmEHLibToExclude)" /> - <_WasmNativeFileForLinking Remove="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(_WasmSIMDLibToExclude)" /> + <_WasmNativeFileForLinking Remove="$(_WasmSIMDLibToExclude)" /> <_WasmNativeFileForLinking Include="-lstdc++" /> <_WasmNativeFileForLinking Include="@(NativeFileReference)" /> diff --git a/src/mono/wasi/wasi.proj b/src/mono/wasi/wasi.proj index 66fcd6e7fe4b71..e0485628a3ee8e 100644 --- a/src/mono/wasi/wasi.proj +++ b/src/mono/wasi/wasi.proj @@ -6,6 +6,7 @@ true false false + false $(ArtifactsObjDir)wasi @@ -90,6 +91,7 @@ { "identity": "EnableDiagnostics", "defaultValueInRuntimePack": "$(EnableDiagnostics)" }, { "identity": "WasmProfilers", "defaultValueInRuntimePack": "$(WasmProfilers)" }, { "identity": "WasmEnableSIMD", "defaultValueInRuntimePack": "$(WasmEnableSIMD)" }, + { "identity": "WasmEnableRelaxedSimd", "defaultValueInRuntimePack": "$(WasmEnableRelaxedSimd)" }, { "identity": "RunAOTCompilation", "defaultValueInRuntimePack": "$(RunAOTCompilation)" } ] } @@ -154,7 +156,8 @@ $(CMakeBuildRuntimeConfigureCmd) -DMONO_OBJ_INCLUDES="$(MonoObjDir.TrimEnd('\/'))" $(CMakeBuildRuntimeConfigureCmd) -DMONO_ARTIFACTS_DIR="$(MonoArtifactsPath.TrimEnd('\/'))" $(CMakeBuildRuntimeConfigureCmd) -DNATIVE_BIN_DIR="$(NativeBinDir.TrimEnd('\/'))" - $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_COMPILE_OPTIONS="-msimd128" -DCONFIGURATION_INTERPSIMDTABLES_LIB="simd" + $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_COMPILE_OPTIONS="-msimd128;-mrelaxed-simd" -DCONFIGURATION_INTERPSIMDTABLES_LIB="relaxed-simd" + $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_COMPILE_OPTIONS="-msimd128" -DCONFIGURATION_INTERPSIMDTABLES_LIB="simd" $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_INTERPSIMDTABLES_LIB="nosimd" $(CMakeBuildRuntimeConfigureCmd) -DDISABLE_THREADS=0 call "$(RepositoryEngineeringDir)native\init-vs-env.cmd" wasm && $(CMakeBuildRuntimeConfigureCmd) diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/WorkloadRequiredTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/WorkloadRequiredTests.cs index 9dbf10ac2a365e..bf19729961dc31 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/WorkloadRequiredTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/WorkloadRequiredTests.cs @@ -23,6 +23,7 @@ public static (string propertyName, bool triggerValue)[] PropertiesWithTriggerVa { ("RunAOTCompilation", true), ("WasmEnableSIMD", false), + ("WasmEnableRelaxedSimd", true), ("WasmEnableExceptionHandling", false), ("InvariantTimezone", true), //("InvariantGlobalization", true), - not applicable for blazor diff --git a/src/mono/wasm/Wasm.Build.Tests/CoreCLRWasmNativeDefaultsTests.cs b/src/mono/wasm/Wasm.Build.Tests/CoreCLRWasmNativeDefaultsTests.cs index c7e27fd6499bd3..9ae4c6ea565dd5 100644 --- a/src/mono/wasm/Wasm.Build.Tests/CoreCLRWasmNativeDefaultsTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/CoreCLRWasmNativeDefaultsTests.cs @@ -32,6 +32,7 @@ public CoreCLRWasmNativeDefaultsTests(ITestOutputHelper output, SharedBuildPerTe { "false", false }, { "false", false }, { "false", false }, + { "false", false }, // property left unset -> no relink { "", false }, // casing must not matter, MSBuild string comparison is case-insensitive @@ -40,6 +41,7 @@ public CoreCLRWasmNativeDefaultsTests(ITestOutputHelper output, SharedBuildPerTe { "true", true }, { "true", true }, { "true", true }, + { "true", true }, { "67108864", true }, // EmccInitialHeapSize is the documented browser property and EmccTotalMemory its legacy // alias; both must be normalized into WasmInitialHeapSize before the registry compares. diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmNativeDefaultsTests.cs b/src/mono/wasm/Wasm.Build.Tests/WasmNativeDefaultsTests.cs index 098662f455dafe..d5e6605189ea02 100644 --- a/src/mono/wasm/Wasm.Build.Tests/WasmNativeDefaultsTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/WasmNativeDefaultsTests.cs @@ -25,6 +25,7 @@ public static TheoryData SettingDiffere List<(string propertyName, bool defaultValueInRuntimePack)> defaults = new() { ("WasmEnableSIMD", true), + ("WasmEnableRelaxedSimd", false), ("WasmEnableExceptionHandling", true), ("InvariantTimezone", false), ("InvariantGlobalization", false), diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmSIMDTests.cs b/src/mono/wasm/Wasm.Build.Tests/WasmSIMDTests.cs index ed7ae6a13bd1ba..53e92e9554e386 100644 --- a/src/mono/wasm/Wasm.Build.Tests/WasmSIMDTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/WasmSIMDTests.cs @@ -66,6 +66,110 @@ public async Task PublishSIMD_AOT(Configuration config, bool aot, bool simd) Assert.Contains(result.TestOutput, m => m.Contains("Hello, World!")); } + [Theory] + [InlineData(false)] + [InlineData(true)] + [TestCategory("mono")] + public Task PublishRelaxedSimdMono(bool relaxedSimd) => PublishRelaxedSimd(relaxedSimd); + + [Theory] + [InlineData(false)] + [InlineData(true)] + [TestCategory("coreclr")] + public Task PublishRelaxedSimdCoreClr(bool relaxedSimd) => PublishRelaxedSimd(relaxedSimd); + + private async Task PublishRelaxedSimd(bool relaxedSimd) + { + Configuration config = Configuration.Debug; + string relaxedSimdValue = relaxedSimd.ToString().ToLowerInvariant(); + string extraProperties = $"{relaxedSimdValue}"; + ProjectInfo info = CopyTestAsset( + config, + aot: false, + TestAsset.WasmBasicTestApp, + $"relaxed_simd_{relaxedSimdValue}", + extraProperties: extraProperties); + UpdateFile( + Path.Combine("Common", "Program.cs"), + IsCoreClrRuntime + ? GetCoreClrRelaxedSimdProgramText(relaxedSimdValue) + : GetMonoRelaxedSimdProgramText(relaxedSimdValue)); + ReplaceMainJsWithMinimalRunMain(); + + PublishProject(info, config, isNativeBuild: relaxedSimd); + + RunResult result = await RunForPublishWithWebServer(new BrowserRunOptions( + config, + TestScenario: "DotnetRun", + ExpectedExitCode: 42)); + string expectedOutput = IsCoreClrRuntime + ? $"RelaxedSimd config: {(relaxedSimd ? "true" : "")}" + : $"RelaxedSimd.IsSupported: {relaxedSimd}"; + Assert.Contains(result.TestOutput, message => message.Contains(expectedOutput)); + } + + private static string GetCoreClrRelaxedSimdProgramText(string expectedConfigValue) => $$""" + using System; + + public class TestClass + { + public static int Main() + { + string configuredValue = AppContext.GetData( + "System.Runtime.Intrinsics.Wasm.RelaxedSimd.IsSupported") as string; + Console.WriteLine($"TestOutput -> RelaxedSimd config: {configuredValue ?? ""}"); + + return configuredValue == {{(expectedConfigValue == "true" ? "\"true\"" : "null")}} + ? 42 + : 1; + } + } + """; + + private static string GetMonoRelaxedSimdProgramText(string expectedIsSupported) => $$""" + using System; + using System.Runtime.Intrinsics; + using System.Runtime.Intrinsics.Wasm; + + public class TestClass + { + public static int Main() + { + bool isSupported = RelaxedSimd.IsSupported; + Console.WriteLine($"TestOutput -> RelaxedSimd.IsSupported: {isSupported}"); + + if (isSupported != {{expectedIsSupported}}) + { + return 1; + } + + if (isSupported) + { + Vector128 result = RelaxedSimd.ConvertToInt32Native( + Vector128.Create(1.75f, -2.25f, 3.0f, -4.99f)); + + if (result != Vector128.Create(1, -2, 3, -4)) + { + return 2; + } + } + else + { + try + { + RelaxedSimd.ConvertToInt32Native(Vector128.Create(1.0f)); + return 3; + } + catch (PlatformNotSupportedException) + { + } + } + + return 42; + } + } + """; + private static string s_simdProgramText = @" using System; using System.Runtime.Intrinsics; diff --git a/src/mono/wasm/build/WasmApp.Common.targets b/src/mono/wasm/build/WasmApp.Common.targets index d592ec19a2a55e..06c45ebdc51ac3 100644 --- a/src/mono/wasm/build/WasmApp.Common.targets +++ b/src/mono/wasm/build/WasmApp.Common.targets @@ -79,6 +79,7 @@ - $(WasmAotProfilePath) - Path to an AOT profile file. - $(WasmEnableExceptionHandling) - Enable support for the WASM post MVP Exception Handling runtime extension. - $(WasmEnableSIMD) - Enable support for the WASM post MVP SIMD runtime extension. + - $(WasmEnableRelaxedSimd) - Enable support for the WASM Relaxed SIMD extension. Requires $(WasmEnableSIMD) == true. - $(WasmEnableWebcil) - Enable conversion of assembly .dlls to Webcil wrapped in .wasm (default: true) - $(WasmIncludeFullIcuData) - Loads full ICU data (icudt.dat). Defaults to false. Only applicable when InvariantGlobalization=false. - $(WasmIcuDataFileName) - Name/path of ICU globalization file loaded to app. Only when InvariantGloblization=false and WasmIncludeFullIcuData=false. @@ -186,6 +187,7 @@ false false + false false false @@ -464,8 +466,11 @@ + + @@ -631,6 +636,7 @@ + diff --git a/src/native/corehost/browserhost/browserhost.cpp b/src/native/corehost/browserhost/browserhost.cpp index e687913cce4913..b3aefce8d6e2ed 100644 --- a/src/native/corehost/browserhost/browserhost.cpp +++ b/src/native/corehost/browserhost/browserhost.cpp @@ -44,6 +44,8 @@ extern "C" pal::hresult_t coreclr_set_error_writer( coreclr_error_writer_callback_fn error_writer); + void coreclr_wasm_set_relaxed_simd_supported(); + #if !GEN_PINVOKE const void* SystemResolveDllImport(const char* name); const void* SystemJSResolveDllImport(const char* name); @@ -110,6 +112,16 @@ extern "C" void* BrowserHost_CreateHostContract(void) extern "C" int BrowserHost_InitializeDotnet(int propertiesCount, const char** propertyKeys, const char** propertyValues) { + for (int i = 0; i < propertiesCount; i++) + { + if ((strcmp(propertyKeys[i], "System.Runtime.Intrinsics.Wasm.RelaxedSimd.IsSupported") == 0) && + (strcmp(propertyValues[i], "true") == 0)) + { + coreclr_wasm_set_relaxed_simd_supported(); + break; + } + } + coreclr_set_error_writer(log_error_info); int retval = coreclr_initialize("/managed", "corehost", propertiesCount, propertyKeys, propertyValues, &CurrentClrInstance, &CurrentAppDomainId); diff --git a/src/tests/JIT/HardwareIntrinsics/Wasm/RelaxedSimd/RelaxedSimdTests.cs b/src/tests/JIT/HardwareIntrinsics/Wasm/RelaxedSimd/RelaxedSimdTests.cs new file mode 100644 index 00000000000000..33089bf5596847 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Wasm/RelaxedSimd/RelaxedSimdTests.cs @@ -0,0 +1,125 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Reflection; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Wasm; +using Xunit; + +public sealed class RelaxedSimdTests +{ + public static bool IsNotSupported => !RelaxedSimd.IsSupported; + + [Fact] + public static void RelaxedSimdIsSupportedReflects() + { + MethodInfo? methodInfo = typeof(RelaxedSimd).GetMethod("get_IsSupported"); + Assert.NotNull(methodInfo); + Assert.Equal(RelaxedSimd.IsSupported, methodInfo.Invoke(null, null)); + } + + [ConditionalFact(typeof(RelaxedSimdTests), nameof(IsNotSupported))] + public static void UnsupportedMethodThrowsPlatformNotSupportedException() + { + Assert.Throws( + () => RelaxedSimd.ConvertToInt32Native(Vector128.Create(1.0f))); + } + + [ConditionalFact(typeof(RelaxedSimd), nameof(RelaxedSimd.IsSupported))] + public static void ConvertToIntegerNativeInRangeMatchesExpected() + { + Assert.Equal( + Vector128.Create(1, -2, 3, -4), + RelaxedSimd.ConvertToInt32Native(Vector128.Create(1.75f, -2.25f, 3.0f, -4.99f))); + Assert.Equal( + Vector128.Create(5, -6, 0, 0), + RelaxedSimd.ConvertToInt32Native(Vector128.Create(5.75, -6.25))); + Assert.Equal( + Vector128.Create(1u, 2u, 3u, 4u), + RelaxedSimd.ConvertToUInt32Native(Vector128.Create(1.75f, 2.25f, 3.0f, 4.99f))); + Assert.Equal( + Vector128.Create(5u, 6u, 0u, 0u), + RelaxedSimd.ConvertToUInt32Native(Vector128.Create(5.75, 6.25))); + } + + [ConditionalFact(typeof(RelaxedSimd), nameof(RelaxedSimd.IsSupported))] + public static void DotProductNativeByteSByteMatchesScalar() + { + Vector128 signed = Vector128.Create((sbyte)-1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15, 16); + Vector128 unsigned = Vector128.Create((byte)2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3); + + Vector128 actual = RelaxedSimd.DotProductNative(signed, unsigned); + + for (int i = 0; i < 8; i++) + { + short expected = (short)(signed[2 * i] * unsigned[2 * i] + signed[2 * i + 1] * unsigned[2 * i + 1]); + Assert.Equal(expected, actual[i]); + } + } + + [ConditionalFact(typeof(RelaxedSimd), nameof(RelaxedSimd.IsSupported))] + public static void DotProductAddNativeByteSByteMatchesScalar() + { + Vector128 signed = Vector128.Create((sbyte)-1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15, 16); + Vector128 unsigned = Vector128.Create((byte)2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3); + Vector128 accumulator = Vector128.Create(100, 200, 300, 400); + + Vector128 actual = RelaxedSimd.DotProductAddNative(signed, unsigned, accumulator); + + for (int i = 0; i < 4; i++) + { + int expected = accumulator[i]; + for (int j = 0; j < 4; j++) + { + expected += signed[4 * i + j] * unsigned[4 * i + j]; + } + Assert.Equal(expected, actual[i]); + } + } + + [ConditionalFact(typeof(RelaxedSimd), nameof(RelaxedSimd.IsSupported))] + public static void MultiplyAddFloatMatchesScalarApproximately() + { + Vector128 left = Vector128.Create(1.5f, 2.25f, -3.125f, 4.0f); + Vector128 right = Vector128.Create(2.0f, -1.5f, 0.5f, 6.25f); + Vector128 addend = Vector128.Create(0.5f, 1.0f, -0.25f, -2.0f); + + Vector128 actual = RelaxedSimd.MultiplyAddEstimate(left, right, addend); + Vector128 unfused = (left * right) + addend; + + const float RelativeTolerance = 1e-5f; + for (int i = 0; i < 4; i++) + { + float tolerance = Math.Max(Math.Abs(unfused[i]), 1.0f) * RelativeTolerance; + Assert.True(Math.Abs(actual[i] - unfused[i]) <= tolerance, + $"lane {i}: relaxed FMA {actual[i]} differs from unfused {unfused[i]} by more than {tolerance}"); + } + } + + [ConditionalFact(typeof(RelaxedSimd), nameof(RelaxedSimd.IsSupported))] + public static void LaneSelectNativeAllOnesAllZerosBehavesLikeConditionalSelect() + { + Vector128 left = Vector128.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector128 right = Vector128.Create((byte)17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector128 mask = Vector128.Create((byte)0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00); + + Vector128 actual = RelaxedSimd.LaneSelectNative(left, right, mask); + Vector128 expected = Vector128.ConditionalSelect(mask, left, right); + + Assert.Equal(expected, actual); + } + + [ConditionalFact(typeof(RelaxedSimd), nameof(RelaxedSimd.IsSupported))] + public static void SwizzleNativeInRangeMatchesVector128Shuffle() + { + Vector128 value = Vector128.Create((byte)10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160); + Vector128 indices = Vector128.Create((byte)15, 0, 14, 1, 13, 2, 12, 3, 11, 4, 10, 5, 9, 6, 8, 7); + + Vector128 actual = RelaxedSimd.SwizzleNative(value, indices); + Vector128 expected = Vector128.Shuffle(value, indices); + + Assert.Equal(expected, actual); + } +} diff --git a/src/tests/JIT/HardwareIntrinsics/Wasm/RelaxedSimd/RelaxedSimdTests_r.csproj b/src/tests/JIT/HardwareIntrinsics/Wasm/RelaxedSimd/RelaxedSimdTests_r.csproj new file mode 100644 index 00000000000000..07a855f245a73a --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Wasm/RelaxedSimd/RelaxedSimdTests_r.csproj @@ -0,0 +1,12 @@ + + + true + Embedded + True + true + true + + + + + diff --git a/src/tests/JIT/HardwareIntrinsics/Wasm/RelaxedSimd/RelaxedSimdTests_ro.csproj b/src/tests/JIT/HardwareIntrinsics/Wasm/RelaxedSimd/RelaxedSimdTests_ro.csproj new file mode 100644 index 00000000000000..9035420319aa24 --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Wasm/RelaxedSimd/RelaxedSimdTests_ro.csproj @@ -0,0 +1,12 @@ + + + true + Embedded + + true + true + + + + +