summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-07-19 00:42:58 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-07-19 00:42:58 +0700
commitb966a4c7e871e8a1bdf50c29626ce40450c3db0c (patch)
treeec7ebe55384a5f92233977dc01e0c541a04af581
parentFactor out Unshuffle methods (diff)
downloadBouncyCastle.NET-ed25519-b966a4c7e871e8a1bdf50c29626ce40450c3db0c.tar.xz
Use intrinsics in several places
-rw-r--r--crypto/src/asn1/DerBitString.cs2
-rw-r--r--crypto/src/math/BigInteger.cs39
-rw-r--r--crypto/src/math/ec/custom/sec/SecT571Field.cs16
-rw-r--r--crypto/src/math/raw/Interleave.cs55
-rw-r--r--crypto/src/util/Integers.cs17
-rw-r--r--crypto/src/util/Longs.cs17
6 files changed, 124 insertions, 22 deletions
diff --git a/crypto/src/asn1/DerBitString.cs b/crypto/src/asn1/DerBitString.cs
index 2b1ff3354..8aab88353 100644
--- a/crypto/src/asn1/DerBitString.cs
+++ b/crypto/src/asn1/DerBitString.cs
@@ -125,7 +125,7 @@ namespace Org.BouncyCastle.Asn1
                 return;
             }
 
-            int bits = BigInteger.BitLen(namedBits);
+            int bits = 32 - Integers.NumberOfLeadingZeros(namedBits);
             int bytes = (bits + 7) / 8;
             Debug.Assert(0 < bytes && bytes <= 4);
 
diff --git a/crypto/src/math/BigInteger.cs b/crypto/src/math/BigInteger.cs
index 50229e2db..f915beafc 100644
--- a/crypto/src/math/BigInteger.cs
+++ b/crypto/src/math/BigInteger.cs
@@ -2,6 +2,9 @@ using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Globalization;
+#if NET5_0_OR_GREATER
+using System.Runtime.Intrinsics.X86;
+#endif
 using System.Runtime.Serialization;
 using System.Text;
 
@@ -136,26 +139,6 @@ namespace Org.BouncyCastle.Math
         public static readonly BigInteger Four;
         public static readonly BigInteger Ten;
 
-        //private readonly static byte[] BitCountTable =
-        //{
-        //    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
-        //    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-        //    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-        //    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-        //    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-        //    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-        //    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-        //    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-        //    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-        //    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-        //    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-        //    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-        //    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-        //    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-        //    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-        //    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
-        //};
-
         private readonly static byte[] BitLengthTable =
         {
             0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
@@ -911,6 +894,13 @@ namespace Org.BouncyCastle.Math
 
         public static int BitCnt(int i)
         {
+#if NET5_0_OR_GREATER
+            if (Popcnt.IsSupported)
+            {
+                return (int)Popcnt.PopCount((uint)i);
+            }
+#endif
+
             uint u = (uint)i;
             u = u - ((u >> 1) & 0x55555555);
             u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
@@ -976,8 +966,15 @@ namespace Org.BouncyCastle.Math
         //
         // BitLen(value) is the number of bits in value.
         //
-        internal static int BitLen(int w)
+        private static int BitLen(int w)
         {
+#if NET5_0_OR_GREATER
+            if (Lzcnt.IsSupported)
+            {
+                return 32 - (int)Lzcnt.LeadingZeroCount((uint)w);
+            }
+#endif
+
             uint v = (uint)w;
             uint t = v >> 24;
             if (t != 0)
diff --git a/crypto/src/math/ec/custom/sec/SecT571Field.cs b/crypto/src/math/ec/custom/sec/SecT571Field.cs
index 4d3f715fa..97bc08d67 100644
--- a/crypto/src/math/ec/custom/sec/SecT571Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT571Field.cs
@@ -1,5 +1,9 @@
 using System;
 using System.Diagnostics;
+#if NET5_0_OR_GREATER
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+#endif
 
 using Org.BouncyCastle.Math.Raw;
 
@@ -399,6 +403,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         protected static void ImplMulwAcc(ulong[] u, ulong x, ulong y, ulong[] z, int zOff)
         {
+#if NET5_0_OR_GREATER
+            if (Pclmulqdq.IsSupported)
+            {
+                var X = Vector128.CreateScalar(x);
+                var Y = Vector128.CreateScalar(y);
+                var Z = Pclmulqdq.CarrylessMultiply(X, Y, 0x00);
+                z[zOff    ] ^= Z.GetElement(0);
+                z[zOff + 1] ^= Z.GetElement(1);
+                return;
+            }
+#endif
+
             //u[0] = 0;
             u[1] = y;
             for (int i = 2; i < 16; i += 2)
diff --git a/crypto/src/math/raw/Interleave.cs b/crypto/src/math/raw/Interleave.cs
index 409ab83e8..560fd76fb 100644
--- a/crypto/src/math/raw/Interleave.cs
+++ b/crypto/src/math/raw/Interleave.cs
@@ -1,4 +1,7 @@
 using System;
+#if NET5_0_OR_GREATER
+using System.Runtime.Intrinsics.X86;
+#endif
 
 namespace Org.BouncyCastle.Math.Raw
 {
@@ -29,6 +32,14 @@ namespace Org.BouncyCastle.Math.Raw
 
         internal static ulong Expand32to64(uint x)
         {
+#if NET5_0_OR_GREATER
+            if (Bmi2.IsSupported)
+            {
+                return (ulong)Bmi2.ParallelBitDeposit(x >> 16, 0x55555555U) << 32
+                    |         Bmi2.ParallelBitDeposit(x      , 0x55555555U);
+            }
+#endif
+
             // "shuffle" low half to even bits and high half to odd bits
             x = Bits.BitPermuteStep(x, 0x0000FF00U, 8);
             x = Bits.BitPermuteStep(x, 0x00F000F0U, 4);
@@ -40,6 +51,15 @@ namespace Org.BouncyCastle.Math.Raw
 
         internal static void Expand64To128(ulong x, ulong[] z, int zOff)
         {
+#if NET5_0_OR_GREATER
+            if (Bmi2.X64.IsSupported)
+            {
+                z[zOff    ] = Bmi2.X64.ParallelBitDeposit(x      , 0x5555555555555555UL);
+                z[zOff + 1] = Bmi2.X64.ParallelBitDeposit(x >> 32, 0x5555555555555555UL);
+                return;
+            }
+#endif
+
             // "shuffle" low half to even bits and high half to odd bits
             x = Bits.BitPermuteStep(x, 0x00000000FFFF0000UL, 16);
             x = Bits.BitPermuteStep(x, 0x0000FF000000FF00UL, 8);
@@ -72,6 +92,15 @@ namespace Org.BouncyCastle.Math.Raw
 
         internal static void Expand64To128Rev(ulong x, ulong[] z, int zOff)
         {
+#if NET5_0_OR_GREATER
+            if (Bmi2.X64.IsSupported)
+            {
+                z[zOff    ] = Bmi2.X64.ParallelBitDeposit(x >> 32, 0xAAAAAAAAAAAAAAAAUL);
+                z[zOff + 1] = Bmi2.X64.ParallelBitDeposit(x      , 0xAAAAAAAAAAAAAAAAUL);
+                return;
+            }
+#endif
+
             // "shuffle" low half to even bits and high half to odd bits
             x = Bits.BitPermuteStep(x, 0x00000000FFFF0000UL, 16);
             x = Bits.BitPermuteStep(x, 0x0000FF000000FF00UL, 8);
@@ -126,6 +155,14 @@ namespace Org.BouncyCastle.Math.Raw
 
         internal static ulong Unshuffle(ulong x)
         {
+#if NET5_0_OR_GREATER
+            if (Bmi2.X64.IsSupported)
+            {
+                return Bmi2.X64.ParallelBitExtract(x, 0xAAAAAAAAAAAAAAAAUL) << 32
+                    |  Bmi2.X64.ParallelBitExtract(x, 0x5555555555555555UL);
+            }
+#endif
+
             // "unshuffle" even bits to low half and odd bits to high half
             x = Bits.BitPermuteStep(x, 0x2222222222222222UL, 1);
             x = Bits.BitPermuteStep(x, 0x0C0C0C0C0C0C0C0CUL, 2);
@@ -137,6 +174,14 @@ namespace Org.BouncyCastle.Math.Raw
 
         internal static ulong Unshuffle(ulong x, out ulong even)
         {
+#if NET5_0_OR_GREATER
+            if (Bmi2.X64.IsSupported)
+            {
+                even = Bmi2.X64.ParallelBitExtract(x, 0x5555555555555555UL);
+                return Bmi2.X64.ParallelBitExtract(x, 0xAAAAAAAAAAAAAAAAUL);
+            }
+#endif
+
             ulong u0 = Unshuffle(x);
             even = u0 & 0x00000000FFFFFFFFUL;
             return u0 >> 32;
@@ -144,6 +189,16 @@ namespace Org.BouncyCastle.Math.Raw
 
         internal static ulong Unshuffle(ulong x0, ulong x1, out ulong even)
         {
+#if NET5_0_OR_GREATER
+            if (Bmi2.X64.IsSupported)
+            {
+                even = Bmi2.X64.ParallelBitExtract(x0, 0x5555555555555555UL)
+                    |  Bmi2.X64.ParallelBitExtract(x1, 0x5555555555555555UL) << 32;
+                return Bmi2.X64.ParallelBitExtract(x0, 0xAAAAAAAAAAAAAAAAUL)
+                    |  Bmi2.X64.ParallelBitExtract(x1, 0xAAAAAAAAAAAAAAAAUL) << 32;
+            }
+#endif
+
             ulong u0 = Unshuffle(x0);
             ulong u1 = Unshuffle(x1);
             even = (u1 << 32) | (u0 & 0x00000000FFFFFFFFUL);
diff --git a/crypto/src/util/Integers.cs b/crypto/src/util/Integers.cs
index 116250375..b32cdfc30 100644
--- a/crypto/src/util/Integers.cs
+++ b/crypto/src/util/Integers.cs
@@ -1,4 +1,7 @@
 using System;
+#if NET5_0_OR_GREATER
+using System.Runtime.Intrinsics.X86;
+#endif
 
 using Org.BouncyCastle.Math.Raw;
 
@@ -42,6 +45,13 @@ namespace Org.BouncyCastle.Utilities
 
         public static int NumberOfLeadingZeros(int i)
         {
+#if NET5_0_OR_GREATER
+            if (Lzcnt.IsSupported)
+            {
+                return (int)Lzcnt.LeadingZeroCount((uint)i);
+            }
+#endif
+
             if (i <= 0)
                 return (~i >> (31 - 5)) & (1 << 5);
 
@@ -57,6 +67,13 @@ namespace Org.BouncyCastle.Utilities
 
         public static int NumberOfTrailingZeros(int i)
         {
+#if NET5_0_OR_GREATER
+            if (Bmi1.IsSupported)
+            {
+                return (int)Bmi1.TrailingZeroCount((uint)i);
+            }
+#endif
+
             int n = DeBruijnTZ[(uint)((i & -i) * 0x0EF96A62) >> 27];
             int m = (((i & 0xFFFF) | (int)((uint)i >> 16)) - 1) >> 31;
             return n - m;
diff --git a/crypto/src/util/Longs.cs b/crypto/src/util/Longs.cs
index e6ff2ea39..ff45a8143 100644
--- a/crypto/src/util/Longs.cs
+++ b/crypto/src/util/Longs.cs
@@ -1,4 +1,7 @@
 using System;
+#if NET5_0_OR_GREATER
+using System.Runtime.Intrinsics.X86;
+#endif
 
 using Org.BouncyCastle.Math.Raw;
 
@@ -45,6 +48,13 @@ namespace Org.BouncyCastle.Utilities
 
         public static int NumberOfLeadingZeros(long i)
         {
+#if NET5_0_OR_GREATER
+            if (Lzcnt.X64.IsSupported)
+            {
+                return (int)Lzcnt.X64.LeadingZeroCount((ulong)i);
+            }
+#endif
+
             int x = (int)(i >> 32), n = 0;
             if (x == 0)
             {
@@ -56,6 +66,13 @@ namespace Org.BouncyCastle.Utilities
 
         public static int NumberOfTrailingZeros(long i)
         {
+#if NET5_0_OR_GREATER
+            if (Bmi1.X64.IsSupported)
+            {
+                return (int)Bmi1.X64.TrailingZeroCount((ulong)i);
+            }
+#endif
+
             int n = DeBruijnTZ[(uint)((ulong)((i & -i) * 0x045FBAC7992A70DAL) >> 58)];
             long m = (((i & 0xFFFFFFFFL) | (long)((ulong)i >> 32)) - 1L) >> 63;
             return n - (int)m;