IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
GHASH_Arm64.cs
Go to the documentation of this file.
1#if NET6_0_OR_GREATER
2
3using System;
5using System.Runtime.InteropServices;
6using System.Runtime.Intrinsics;
7using System.Runtime.Intrinsics.Arm;
8
10{
14 [SkipLocalsInit]
15 static class GHASH_Arm64
16 {
17 private static ReadOnlySpan<long> P => [0x87, 0x87];
18
22 public static bool IsSupported => BitConverter.IsLittleEndian && Aes.IsSupported && AdvSimd.Arm64.IsSupported;
23
33 [MethodImpl(MethodImplOptions.AggressiveInlining)]
34 public static void ProcessBlocks(Span<long> state, ReadOnlySpan<long> subH, ReadOnlySpan<byte> data, int blocks)
35 {
36 // ext\openjdk\hotspot\src\cpu\aarch64\vm\stubGenerator_aarch64.cpp:3322-3395
37 var vzr = Vector128<byte>.Zero;
38
39 var v0 = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(state));
40 var v1 = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(subH));
41 v0 = AdvSimd.ReverseElement8(v0);
42 v0 = AdvSimd.Arm64.ReverseElementBits(v0.AsByte()).AsInt64();
43 v1 = AdvSimd.ReverseElement8(v1);
44 v1 = AdvSimd.Arm64.ReverseElementBits(v1.AsByte()).AsInt64();
45
46 var v26 = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(P));
47
48 var v16 = AdvSimd.ExtractVector128(v1.AsByte(), v1.AsByte(), 0x08).AsInt64();
49 v16 = AdvSimd.Xor(v16, v1);
50
51 {
52 ghash_loop:;
53 var v2 = Vector128Util.LoadUnsafe(in RefUtils.Post(ref data, 0x10));
54 v2 = AdvSimd.Arm64.ReverseElementBits(v2);
55 v2 = AdvSimd.Xor(v0.AsByte(), v2);
56
57 (var v5, var v7) = GHashMultiply(v1, v2, v16);
58 v0 = GHashReduce(v5, v7, v26, vzr);
59
60 if ((--blocks) != 0)
61 {
62 goto ghash_loop;
63 }
64 }
65
66 v1 = AdvSimd.ReverseElement8(v0);
67 v1 = AdvSimd.Arm64.ReverseElementBits(v1.AsByte()).AsInt64();
68 v1.CopyTo(state);
69 }
70
71 [MethodImpl(MethodImplOptions.AggressiveInlining)]
72 private static (Vector128<long> Lower, Vector128<long> Upper) GHashMultiply(Vector128<long> a, Vector128<byte> b, Vector128<long> a1_xor_a0)
73 {
74 // ext\openjdk\hotspot\src\cpu\aarch64\vm\stubGenerator_aarch64.cpp:3207-3240
75 var tmp1 = AdvSimd.ExtractVector128(b, b, 0x08);
76 var result_hi = Aes.PolynomialMultiplyWideningUpper(b.AsInt64(), a);
77 tmp1 = AdvSimd.Xor(tmp1, b);
78 var result_lo = Aes.PolynomialMultiplyWideningLower(b.GetLower().AsInt64(), a.GetLower());
79 var tmp2 = Aes.PolynomialMultiplyWideningLower(tmp1.GetLower().AsInt64(), a1_xor_a0.GetLower());
80
81 var tmp4 = AdvSimd.ExtractVector128(result_lo.AsByte(), result_hi.AsByte(), 0x08);
82 var tmp3 = AdvSimd.Xor(result_hi, result_lo);
83 tmp2 = AdvSimd.Xor(tmp2, tmp4.AsInt64());
84 tmp2 = AdvSimd.Xor(tmp2, tmp3);
85
86 result_hi = AdvSimd.Arm64.InsertSelectedScalar(result_hi, 0, tmp2, 1);
87 result_lo = AdvSimd.Arm64.InsertSelectedScalar(result_lo, 1, tmp2, 0);
88
89 return (result_lo, result_hi);
90 }
91
92 [MethodImpl(MethodImplOptions.AggressiveInlining)]
93 private static Vector128<long> GHashReduce(Vector128<long> lo, Vector128<long> hi, Vector128<long> p, Vector128<byte> z)
94 {
95 // ext\openjdk\hotspot\src\cpu\aarch64\vm\stubGenerator_aarch64.cpp:3242-3268
96 var t0 = Aes.PolynomialMultiplyWideningUpper(hi, p);
97 var t1 = AdvSimd.ExtractVector128(t0.AsByte(), z, 8);
98 hi = AdvSimd.Xor(hi, t1.AsInt64());
99 t1 = AdvSimd.ExtractVector128(z, t0.AsByte(), 8);
100 lo = AdvSimd.Xor(lo, t1.AsInt64());
101 t0 = Aes.PolynomialMultiplyWideningLower(hi.GetLower(), p.GetLower());
102 return AdvSimd.Xor(lo, t0);
103 }
104 }
105}
106
107#endif