1#if NETCOREAPP3_0_OR_GREATER
5using System.Runtime.InteropServices;
6using System.Runtime.Intrinsics;
7using System.Runtime.Intrinsics.X86;
16 static class GHASH_x86
22 public static bool IsSupported => Pclmulqdq.IsSupported && Ssse3.IsSupported;
24 static ReadOnlySpan<int> ByteSwapMask => [0x0c0d0e0f, 0x08090a0b, 0x04050607, 0x00010203];
26 static ReadOnlySpan<int> LongSwapMask => [0x0b0a0908, 0x0f0e0d0c, 0x03020100, 0x07060504];
37 [MethodImpl(MethodImplOptions.AggressiveInlining)]
38 public static void ProcessBlocks(Span<long> state, ReadOnlySpan<long> subH, ReadOnlySpan<byte> data,
int blocks)
41 Vector128<int> xmm_temp0, xmm_temp1, xmm_temp2, xmm_temp3, xmm_temp4, xmm_temp5, xmm_temp6, xmm_temp7;
42 xmm_temp0 = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(state)).AsInt32();
43 xmm_temp0 = Ssse3.Shuffle(xmm_temp0.AsByte(), Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(LongSwapMask)).AsByte()).AsInt32();
44 xmm_temp1 = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(subH)).AsInt32();
45 xmm_temp1 = Ssse3.Shuffle(xmm_temp1.AsByte(), Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(LongSwapMask)).AsByte()).AsInt32();
48 xmm_temp2 = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(data)).AsInt32();
49 xmm_temp2 = Ssse3.Shuffle(xmm_temp2.AsByte(), Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(ByteSwapMask)).AsByte()).AsInt32();
50 xmm_temp0 = Sse2.Xor(xmm_temp0, xmm_temp2);
52 xmm_temp3 = xmm_temp0;
53 xmm_temp3 = Pclmulqdq.CarrylessMultiply(xmm_temp3.AsInt64(), xmm_temp1.AsInt64(), 0).AsInt32();
54 xmm_temp4 = xmm_temp0;
55 xmm_temp4 = Pclmulqdq.CarrylessMultiply(xmm_temp4.AsInt64(), xmm_temp1.AsInt64(), 16).AsInt32();
57 xmm_temp5 = xmm_temp0;
58 xmm_temp5 = Pclmulqdq.CarrylessMultiply(xmm_temp5.AsInt64(), xmm_temp1.AsInt64(), 1).AsInt32();
59 xmm_temp6 = xmm_temp0;
60 xmm_temp6 = Pclmulqdq.CarrylessMultiply(xmm_temp6.AsInt64(), xmm_temp1.AsInt64(), 17).AsInt32();
62 xmm_temp4 = Sse2.Xor(xmm_temp4, xmm_temp5);
64 xmm_temp5 = xmm_temp4;
65 xmm_temp4 = Sse2.ShiftRightLogical128BitLane(xmm_temp4, 8);
66 xmm_temp5 = Sse2.ShiftLeftLogical128BitLane(xmm_temp5, 8);
67 xmm_temp3 = Sse2.Xor(xmm_temp3, xmm_temp5);
68 xmm_temp6 = Sse2.Xor(xmm_temp6, xmm_temp4);
70 xmm_temp7 = xmm_temp3;
71 xmm_temp4 = xmm_temp6;
72 xmm_temp3 = Sse2.ShiftLeftLogical(xmm_temp3, 1);
73 xmm_temp6 = Sse2.ShiftLeftLogical(xmm_temp6, 1);
74 xmm_temp7 = Sse2.ShiftRightLogical(xmm_temp7, 31);
75 xmm_temp4 = Sse2.ShiftRightLogical(xmm_temp4, 31);
76 xmm_temp5 = xmm_temp7;
77 xmm_temp4 = Sse2.ShiftLeftLogical128BitLane(xmm_temp4, 4);
78 xmm_temp7 = Sse2.ShiftLeftLogical128BitLane(xmm_temp7, 4);
79 xmm_temp5 = Sse2.ShiftRightLogical128BitLane(xmm_temp5, 12);
80 xmm_temp3 = Sse2.Or(xmm_temp3, xmm_temp7);
81 xmm_temp6 = Sse2.Or(xmm_temp6, xmm_temp4);
82 xmm_temp6 = Sse2.Or(xmm_temp6, xmm_temp5);
84 xmm_temp7 = xmm_temp3;
85 xmm_temp4 = xmm_temp3;
86 xmm_temp5 = xmm_temp3;
87 xmm_temp7 = Sse2.ShiftLeftLogical(xmm_temp7, 31);
88 xmm_temp4 = Sse2.ShiftLeftLogical(xmm_temp4, 30);
89 xmm_temp5 = Sse2.ShiftLeftLogical(xmm_temp5, 25);
90 xmm_temp7 = Sse2.Xor(xmm_temp7, xmm_temp4);
91 xmm_temp7 = Sse2.Xor(xmm_temp7, xmm_temp5);
92 xmm_temp4 = xmm_temp7;
93 xmm_temp7 = Sse2.ShiftLeftLogical128BitLane(xmm_temp7, 12);
94 xmm_temp4 = Sse2.ShiftRightLogical128BitLane(xmm_temp4, 4);
95 xmm_temp3 = Sse2.Xor(xmm_temp3, xmm_temp7);
97 xmm_temp2 = xmm_temp3;
98 xmm_temp7 = xmm_temp3;
99 xmm_temp5 = xmm_temp3;
100 xmm_temp2 = Sse2.ShiftRightLogical(xmm_temp2, 1);
101 xmm_temp7 = Sse2.ShiftRightLogical(xmm_temp7, 2);
102 xmm_temp5 = Sse2.ShiftRightLogical(xmm_temp5, 7);
103 xmm_temp2 = Sse2.Xor(xmm_temp2, xmm_temp7);
104 xmm_temp2 = Sse2.Xor(xmm_temp2, xmm_temp5);
105 xmm_temp2 = Sse2.Xor(xmm_temp2, xmm_temp4);
106 xmm_temp3 = Sse2.Xor(xmm_temp3, xmm_temp2);
107 xmm_temp6 = Sse2.Xor(xmm_temp6, xmm_temp3);
113 xmm_temp0 = xmm_temp6;
114 data = MemoryMarshal.CreateReadOnlySpan(
ref Unsafe.Add(
ref Unsafe.AsRef(in MemoryMarshal.GetReference(data)), 16), data.Length - 16);
118 Ssse3.Shuffle(xmm_temp6.AsByte(), Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(LongSwapMask)).AsByte()).AsInt64().CopyTo(state);