summaryrefslogtreecommitdiff
path: root/src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.cs')
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.cs20
1 files changed, 13 insertions, 7 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.cs b/src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.cs
index b37b01779d..bf2bccf879 100644
--- a/src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.cs
@@ -1009,10 +1009,14 @@ namespace System.Text
{
Debug.Assert(AllCharsInUInt64AreAscii(value));
- if (Bmi2.X64.IsSupported)
+ if (Sse2.X64.IsSupported)
{
- // BMI2 will work regardless of the processor's endianness.
- Unsafe.WriteUnaligned(ref outputBuffer, (uint)Bmi2.X64.ParallelBitExtract(value, 0x00FF00FF_00FF00FFul));
+ // Narrows a vector of words [ w0 w1 w2 w3 ] to a vector of bytes
+ // [ b0 b1 b2 b3 b0 b1 b2 b3 ], then writes 4 bytes (32 bits) to the destination.
+
+ Vector128<short> vecWide = Sse2.X64.ConvertScalarToVector128UInt64(value).AsInt16();
+ Vector128<uint> vecNarrow = Sse2.PackUnsignedSaturate(vecWide, vecWide).AsUInt32();
+ Unsafe.WriteUnaligned<uint>(ref outputBuffer, Sse2.ConvertToUInt32(vecNarrow));
}
else
{
@@ -1694,14 +1698,16 @@ namespace System.Text
/// writes them to the output buffer with machine endianness.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void WidenFourAsciiBytesToUtf16AndWriteToBuffer(ref char outputBuffer, uint value)
+ internal static void WidenFourAsciiBytesToUtf16AndWriteToBuffer(ref char outputBuffer, uint value)
{
Debug.Assert(AllBytesInUInt32AreAscii(value));
- if (Bmi2.X64.IsSupported)
+ if (Sse2.X64.IsSupported)
{
- // BMI2 will work regardless of the processor's endianness.
- Unsafe.WriteUnaligned(ref Unsafe.As<char, byte>(ref outputBuffer), Bmi2.X64.ParallelBitDeposit(value, 0x00FF00FF_00FF00FFul));
+ Debug.Assert(BitConverter.IsLittleEndian, "SSE2 widening assumes little-endian.");
+ Vector128<byte> vecNarrow = Sse2.ConvertScalarToVector128UInt32(value).AsByte();
+ Vector128<ulong> vecWide = Sse2.UnpackLow(vecNarrow, Vector128<byte>.Zero).AsUInt64();
+ Unsafe.WriteUnaligned<ulong>(ref Unsafe.As<char, byte>(ref outputBuffer), Sse2.X64.ConvertToUInt64(vecWide));
}
else
{