[PATCH] Add i386/SSSE3 implementation of SHA512

Jussi Kivilinna jussi.kivilinna at iki.fi
Sun Nov 3 21:49:46 CET 2019


* LICENSES: Add 'sha512-ssse3-i386.c'.
* configure.ac: Add 'sha512-ssse3-i386.lo'.
* cipher/Makefile.am: Add 'sha512-ssse3-i386.c'.
* cipher/sha512-ssse3-i386.c: New.
* cipher/sha512.c (USE_SSSE3_I386, _gcry_sha512_transform_i386_ssse3)
(do_sha512_transform_i386_ssse3): New.
(_gcry_sha512_transform_arm) [USE_SSSE3_I386]: Use i386/SSSE3 transform
function if supported by CPU.
--

Benchmark on AMD Ryzen 7 3700X:

Before:
                |  nanosecs/byte   mebibytes/sec   cycles/byte  auto Mhz
 SHA512         |     12.58 ns/B     75.79 MiB/s     55.06 c/B      4375

After (~4.5x faster):
                |  nanosecs/byte   mebibytes/sec   cycles/byte  auto Mhz
 SHA512         |      2.78 ns/B     343.3 MiB/s     12.09 c/B      4351

Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 0 files changed

diff --git a/LICENSES b/LICENSES
index f6733a692..31f8eae83 100644
--- a/LICENSES
+++ b/LICENSES
@@ -18,6 +18,7 @@ with any binary distributions derived from the GNU C Library.
   - cipher/sha512-avx-amd64.S
   - cipher/sha512-avx2-bmi2-amd64.S
   - cipher/sha512-ssse3-amd64.S
+  - cipher/sha512-ssse3-i386.c
 
 #+begin_quote
   Copyright (c) 2012, Intel Corporation
diff --git a/cipher/Makefile.am b/cipher/Makefile.am
index dc63a736f..020a96162 100644
--- a/cipher/Makefile.am
+++ b/cipher/Makefile.am
@@ -117,7 +117,7 @@ EXTRA_libcipher_la_SOURCES = \
 	sha512.c sha512-ssse3-amd64.S sha512-avx-amd64.S \
 	sha512-avx2-bmi2-amd64.S \
 	sha512-armv7-neon.S sha512-arm.S \
-	sha512-ppc.c \
+	sha512-ppc.c sha512-ssse3-i386.c \
 	sm3.c \
 	keccak.c keccak_permute_32.h keccak_permute_64.h keccak-armv7-neon.S \
 	stribog.c \
@@ -197,6 +197,12 @@ sha256-intel-shaext.o: $(srcdir)/sha256-intel-shaext.c Makefile
 sha256-intel-shaext.lo: $(srcdir)/sha256-intel-shaext.c Makefile
 	`echo $(LTCOMPILE) -c $< | $(instrumentation_munging) `
 
+sha256-ssse3-i386.o: $(srcdir)/sha256-ssse3-i386.c Makefile
+	`echo $(COMPILE) -c $< | $(instrumentation_munging) `
+
+sha256-ssse3-i386.lo: $(srcdir)/sha256-ssse3-i386.c Makefile
+	`echo $(LTCOMPILE) -c $< | $(instrumentation_munging) `
+
 crc-intel-pclmul.o: $(srcdir)/crc-intel-pclmul.c Makefile
 	`echo $(COMPILE) -c $< | $(instrumentation_munging) `
 
diff --git a/cipher/sha512-ssse3-i386.c b/cipher/sha512-ssse3-i386.c
new file mode 100644
index 000000000..1b53e132d
--- /dev/null
+++ b/cipher/sha512-ssse3-i386.c
@@ -0,0 +1,401 @@
+/* sha512-ssse3-i386.c - i386/SSSE3 implementation of SHA-512 transform
+ * Copyright (C) 2019 Jussi Kivilinna <jussi.kivilinna at iki.fi>
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * SHA512 Message Expansion (I2 and W2 macros) based on implementation
+ * from file "sha512-ssse3-amd64.s":
+ ************************************************************************
+ * Copyright (c) 2012, Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * * Neither the name of the Intel Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ************************************************************************
+ */
+
+#include <config.h>
+
+#if defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ >= 4 && \
+    defined(HAVE_GCC_INLINE_ASM_SSSE3) && defined(USE_SHA512)
+
+#include "bufhelp.h"
+
+
+#if _GCRY_GCC_VERSION >= 40400 /* 4.4 */
+/* Prevent compiler from issuing SSE/MMX instructions between asm blocks. */
+#  pragma GCC target("no-sse")
+#  pragma GCC target("no-mmx")
+#endif
+#if __clang__
+#  pragma clang attribute push (__attribute__((target("no-sse"))), apply_to = function)
+#  pragma clang attribute push (__attribute__((target("no-mmx"))), apply_to = function)
+#endif
+
+
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+#define NO_INLINE __attribute__((noinline))
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR          NO_INSTRUMENT_FUNCTION
+#define ASM_FUNC_ATTR_INLINE   ASM_FUNC_ATTR ALWAYS_INLINE
+#define ASM_FUNC_ATTR_NOINLINE ASM_FUNC_ATTR NO_INLINE
+
+
+static const u64 K[80] __attribute__ ((aligned (16))) =
+  {
+    U64_C(0x428a2f98d728ae22), U64_C(0x7137449123ef65cd),
+    U64_C(0xb5c0fbcfec4d3b2f), U64_C(0xe9b5dba58189dbbc),
+    U64_C(0x3956c25bf348b538), U64_C(0x59f111f1b605d019),
+    U64_C(0x923f82a4af194f9b), U64_C(0xab1c5ed5da6d8118),
+    U64_C(0xd807aa98a3030242), U64_C(0x12835b0145706fbe),
+    U64_C(0x243185be4ee4b28c), U64_C(0x550c7dc3d5ffb4e2),
+    U64_C(0x72be5d74f27b896f), U64_C(0x80deb1fe3b1696b1),
+    U64_C(0x9bdc06a725c71235), U64_C(0xc19bf174cf692694),
+    U64_C(0xe49b69c19ef14ad2), U64_C(0xefbe4786384f25e3),
+    U64_C(0x0fc19dc68b8cd5b5), U64_C(0x240ca1cc77ac9c65),
+    U64_C(0x2de92c6f592b0275), U64_C(0x4a7484aa6ea6e483),
+    U64_C(0x5cb0a9dcbd41fbd4), U64_C(0x76f988da831153b5),
+    U64_C(0x983e5152ee66dfab), U64_C(0xa831c66d2db43210),
+    U64_C(0xb00327c898fb213f), U64_C(0xbf597fc7beef0ee4),
+    U64_C(0xc6e00bf33da88fc2), U64_C(0xd5a79147930aa725),
+    U64_C(0x06ca6351e003826f), U64_C(0x142929670a0e6e70),
+    U64_C(0x27b70a8546d22ffc), U64_C(0x2e1b21385c26c926),
+    U64_C(0x4d2c6dfc5ac42aed), U64_C(0x53380d139d95b3df),
+    U64_C(0x650a73548baf63de), U64_C(0x766a0abb3c77b2a8),
+    U64_C(0x81c2c92e47edaee6), U64_C(0x92722c851482353b),
+    U64_C(0xa2bfe8a14cf10364), U64_C(0xa81a664bbc423001),
+    U64_C(0xc24b8b70d0f89791), U64_C(0xc76c51a30654be30),
+    U64_C(0xd192e819d6ef5218), U64_C(0xd69906245565a910),
+    U64_C(0xf40e35855771202a), U64_C(0x106aa07032bbd1b8),
+    U64_C(0x19a4c116b8d2d0c8), U64_C(0x1e376c085141ab53),
+    U64_C(0x2748774cdf8eeb99), U64_C(0x34b0bcb5e19b48a8),
+    U64_C(0x391c0cb3c5c95a63), U64_C(0x4ed8aa4ae3418acb),
+    U64_C(0x5b9cca4f7763e373), U64_C(0x682e6ff3d6b2b8a3),
+    U64_C(0x748f82ee5defb2fc), U64_C(0x78a5636f43172f60),
+    U64_C(0x84c87814a1f0ab72), U64_C(0x8cc702081a6439ec),
+    U64_C(0x90befffa23631e28), U64_C(0xa4506cebde82bde9),
+    U64_C(0xbef9a3f7b2c67915), U64_C(0xc67178f2e372532b),
+    U64_C(0xca273eceea26619c), U64_C(0xd186b8c721c0c207),
+    U64_C(0xeada7dd6cde0eb1e), U64_C(0xf57d4f7fee6ed178),
+    U64_C(0x06f067aa72176fba), U64_C(0x0a637dc5a2c898a6),
+    U64_C(0x113f9804bef90dae), U64_C(0x1b710b35131c471b),
+    U64_C(0x28db77f523047d84), U64_C(0x32caab7b40c72493),
+    U64_C(0x3c9ebe0a15c9bebc), U64_C(0x431d67c49c100d4c),
+    U64_C(0x4cc5d4becb3e42b6), U64_C(0x597f299cfc657e2a),
+    U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817)
+  };
+
+static const unsigned char bshuf_mask[16] __attribute__ ((aligned (16))) =
+  { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 };
+
+
+/* SHA2 round */
+#define RA "%%mm0"
+#define RB "%%mm1"
+#define RC "%%mm2"
+#define RD "%%mm3"
+#define RE "%%mm4"
+#define RF "%%mm5"
+#define RG "%%mm6"
+#define RH "%%mm7"
+
+#define Rx(a,b,c,d,e,f,g,h,wk) \
+	asm volatile (/* Cho + Sum1 */					\
+		      "movq2dq "a", %%xmm2;\n\t"			\
+		      "movq "e", "a";\n\t"				\
+		      "movq2dq "c", %%xmm3;\n\t"			\
+		      "movq "e", "c";\n\t"				\
+		      "movq2dq "b", %%xmm4;\n\t"			\
+		      "movq "e", "b";\n\t"				\
+		      "psrlq $(41-18), "c";\n\t"			\
+		      "pandn "g", "a";\n\t"				\
+		      "pxor "e", "c";\n\t"				\
+		      "pand "f", "b";\n\t"				\
+		      "psrlq $(18-14), "c";\n\t"			\
+		      "paddq "a", "h";\n\t"				\
+		      wk(a)						\
+		      "pxor "e", "c";\n\t"				\
+		      "paddq "b", "h";\n\t"				\
+		      "psrlq $(14), "c";\n\t"				\
+		      "movq "e", "b";\n\t"				\
+		      "psllq $(50-46), "b";\n\t"			\
+		      "paddq "a", "h";\n\t"				\
+		      "movdq2q %%xmm2, "a";\n\t"			\
+		      "pxor "e", "b";\n\t"				\
+		      "psllq $(46-23), "b";\n\t"			\
+		      "pxor "e", "b";\n\t"				\
+		      "psllq $(23), "b";\n\t"				\
+		      "pxor "b", "c";\n\t"				\
+		      "movdq2q %%xmm4, "b";\n\t"			\
+		      "paddq "c", "h";\n\t"				\
+		      "movdq2q %%xmm3, "c";\n\t"			\
+		      \
+		      /* Maj + Sum0 */ \
+		      "movq2dq "e", %%xmm2;\n\t"			\
+		      "movq "a", "e";\n\t"				\
+		      "movq2dq "g", %%xmm3;\n\t"			\
+		      "movq "a", "g";\n\t"				\
+		      "movq2dq "f", %%xmm4;\n\t"			\
+		      "movq "a", "f";\n\t"				\
+		      "psrlq $(39-34), "g";\n\t"			\
+		      "pxor "b", "e";\n\t"				\
+		      "pxor "a", "g";\n\t"				\
+		      "pand "b", "f";\n\t"				\
+		      "psrlq $(34-28), "g";\n\t"			\
+		      "pand "c", "e";\n\t"				\
+		      "pxor "a", "g";\n\t"				\
+		      "paddq "h", "d";\n\t"				\
+		      "paddq "f", "h";\n\t"				\
+		      "movdq2q %%xmm4, "f";\n\t"			\
+		      "psrlq $28, "g";\n\t"				\
+		      "paddq "e", "h";\n\t"				\
+		      "movq "a", "e";\n\t"				\
+		      "psllq $(36-30), "e";\n\t"			\
+		      "pxor "a", "e";\n\t"				\
+		      "psllq $(30-25), "e";\n\t"			\
+		      "pxor "a", "e";\n\t"				\
+		      "psllq $(25), "e";\n\t"				\
+		      "pxor "e", "g";\n\t"				\
+		      "movdq2q %%xmm2, "e";\n\t"			\
+		      "paddq "g", "h";\n\t"				\
+		      "movdq2q %%xmm3, "g";\n\t"			\
+		      \
+		      :							\
+		      :							\
+		      : "memory" )
+
+#define WK0(tmp)      "movdq2q %%xmm0, "tmp";\n\t"			\
+		      "pshufd $0xee, %%xmm0, %%xmm0;\n\t"
+
+#define WK1(tmp)      "movdq2q %%xmm0, "tmp";\n\t"
+
+/* Message expansion */
+#define I2(i) \
+	asm volatile ("movdqu %[inbuf], %%xmm0;\n\t"			\
+		      "pshufb %%xmm5, %%xmm0;\n\t"			\
+		      "movdqu %%xmm0, %[w];\n\t"			\
+		      "paddq %[k], %%xmm0;\n\t"				\
+		      :							\
+		      : [k] "m" (K[i]),					\
+		        [w] "m" (w[i]),					\
+		        [inbuf] "m" (data[(i)*8])			\
+		      : "memory" )
+
+#define W2(i) \
+	asm volatile ("movdqu %[w_t_m_2], %%xmm2;\n\t"			\
+		      "movdqa %%xmm2, %%xmm0;\n\t"			\
+		      "movdqu %[w_t_m_15], %%xmm5;\n\t"			\
+		      "movdqa %%xmm5, %%xmm3;\n\t"			\
+		      "psrlq $(61-19), %%xmm0;\n\t"			\
+		      "psrlq $(8-7), %%xmm3;\n\t"			\
+		      "pxor %%xmm2, %%xmm0;\n\t"			\
+		      "pxor %%xmm5, %%xmm3;\n\t"			\
+		      "psrlq $(19-6), %%xmm0;\n\t"			\
+		      "psrlq $(7-1), %%xmm3;\n\t"			\
+		      "pxor %%xmm2, %%xmm0;\n\t"			\
+		      "pxor %%xmm5, %%xmm3;\n\t"			\
+		      "psrlq $6, %%xmm0;\n\t"				\
+		      "psrlq $1, %%xmm3;\n\t"				\
+		      "movdqa %%xmm2, %%xmm1;\n\t"			\
+		      "movdqa %%xmm5, %%xmm4;\n\t"			\
+		      "psllq $(61-19), %%xmm1;\n\t"			\
+		      "psllq $(8-1), %%xmm4;\n\t"			\
+		      "pxor %%xmm2, %%xmm1;\n\t"			\
+		      "pxor %%xmm5, %%xmm4;\n\t"			\
+		      "psllq $(64-61), %%xmm1;\n\t"			\
+		      "psllq $(64-8), %%xmm4;\n\t"			\
+		      "pxor %%xmm1, %%xmm0;\n\t"			\
+		      "movdqu %[w_t_m_16], %%xmm2;\n\t"			\
+		      "pxor %%xmm4, %%xmm3;\n\t"			\
+		      "movdqu %[w_t_m_7], %%xmm1;\n\t"			\
+		      "paddq %%xmm3, %%xmm0;\n\t"			\
+		      "paddq %%xmm2, %%xmm0;\n\t"			\
+		      "paddq %%xmm1, %%xmm0;\n\t"			\
+		      "movdqu %%xmm0, %[w_t_m_0];\n\t"			\
+		      "paddq %[k], %%xmm0;\n\t"				\
+		      :	[w_t_m_0] "=m" (w[(i)-0])			\
+		      : [k] "m" (K[i]),					\
+		        [w_t_m_2] "m" (w[(i)-2]),			\
+		        [w_t_m_7] "m" (w[(i)-7]),			\
+		        [w_t_m_15] "m" (w[(i)-15]),			\
+		        [w_t_m_16] "m" (w[(i)-16])			\
+		      : "memory" )
+
+unsigned int ASM_FUNC_ATTR
+_gcry_sha512_transform_i386_ssse3(u64 state[8], const unsigned char *data,
+				  size_t nblks)
+{
+  unsigned int t;
+  u64 w[80];
+
+  /* Load state to MMX registers. */
+  asm volatile ("emms;\n\t"
+		"movq 8*0(%[state]), "RA";\n\t"
+		"movq 8*1(%[state]), "RB";\n\t"
+		"movq 8*2(%[state]), "RC";\n\t"
+		"movq 8*3(%[state]), "RD";\n\t"
+		"movq 8*4(%[state]), "RE";\n\t"
+		"movq 8*5(%[state]), "RF";\n\t"
+		"movq 8*6(%[state]), "RG";\n\t"
+		"movq 8*7(%[state]), "RH";\n\t"
+		:
+		: [state] "r" (state)
+		: "memory" );
+
+  while (nblks)
+    {
+      asm volatile ("movdqa %[bshuf_mask], %%xmm5;\n\t"
+		    :
+		    : [bshuf_mask] "m" (*bshuf_mask)
+		    : "memory" );
+
+      I2(0);
+      Rx(RA, RB, RC, RD, RE, RF, RG, RH, WK0);
+      Rx(RH, RA, RB, RC, RD, RE, RF, RG, WK1);
+      I2(2);
+      Rx(RG, RH, RA, RB, RC, RD, RE, RF, WK0);
+      Rx(RF, RG, RH, RA, RB, RC, RD, RE, WK1);
+      I2(4);
+      Rx(RE, RF, RG, RH, RA, RB, RC, RD, WK0);
+      Rx(RD, RE, RF, RG, RH, RA, RB, RC, WK1);
+      I2(6);
+      Rx(RC, RD, RE, RF, RG, RH, RA, RB, WK0);
+      Rx(RB, RC, RD, RE, RF, RG, RH, RA, WK1);
+      I2(8);
+      Rx(RA, RB, RC, RD, RE, RF, RG, RH, WK0);
+      Rx(RH, RA, RB, RC, RD, RE, RF, RG, WK1);
+      I2(10);
+      Rx(RG, RH, RA, RB, RC, RD, RE, RF, WK0);
+      Rx(RF, RG, RH, RA, RB, RC, RD, RE, WK1);
+      I2(12);
+      Rx(RE, RF, RG, RH, RA, RB, RC, RD, WK0);
+      Rx(RD, RE, RF, RG, RH, RA, RB, RC, WK1);
+      I2(14);
+      Rx(RC, RD, RE, RF, RG, RH, RA, RB, WK0);
+      Rx(RB, RC, RD, RE, RF, RG, RH, RA, WK1);
+      data += 128;
+
+      for (t = 16; t < 80; t += 16)
+	{
+	  W2(t + 0);
+	  Rx(RA, RB, RC, RD, RE, RF, RG, RH, WK0);
+	  Rx(RH, RA, RB, RC, RD, RE, RF, RG, WK1);
+	  W2(t + 2);
+	  Rx(RG, RH, RA, RB, RC, RD, RE, RF, WK0);
+	  Rx(RF, RG, RH, RA, RB, RC, RD, RE, WK1);
+	  W2(t + 4);
+	  Rx(RE, RF, RG, RH, RA, RB, RC, RD, WK0);
+	  Rx(RD, RE, RF, RG, RH, RA, RB, RC, WK1);
+	  W2(t + 6);
+	  Rx(RC, RD, RE, RF, RG, RH, RA, RB, WK0);
+	  Rx(RB, RC, RD, RE, RF, RG, RH, RA, WK1);
+	  W2(t + 8);
+	  Rx(RA, RB, RC, RD, RE, RF, RG, RH, WK0);
+	  Rx(RH, RA, RB, RC, RD, RE, RF, RG, WK1);
+	  W2(t + 10);
+	  Rx(RG, RH, RA, RB, RC, RD, RE, RF, WK0);
+	  Rx(RF, RG, RH, RA, RB, RC, RD, RE, WK1);
+	  W2(t + 12);
+	  Rx(RE, RF, RG, RH, RA, RB, RC, RD, WK0);
+	  Rx(RD, RE, RF, RG, RH, RA, RB, RC, WK1);
+	  W2(t + 14);
+	  Rx(RC, RD, RE, RF, RG, RH, RA, RB, WK0);
+	  Rx(RB, RC, RD, RE, RF, RG, RH, RA, WK1);
+	}
+
+      asm volatile ("paddq 8*0(%[state]), "RA";\n\t"
+		    "paddq 8*1(%[state]), "RB";\n\t"
+		    "paddq 8*2(%[state]), "RC";\n\t"
+		    "paddq 8*3(%[state]), "RD";\n\t"
+		    "paddq 8*4(%[state]), "RE";\n\t"
+		    "paddq 8*5(%[state]), "RF";\n\t"
+		    "paddq 8*6(%[state]), "RG";\n\t"
+		    "paddq 8*7(%[state]), "RH";\n\t"
+		    "movq "RA", 8*0(%[state]);\n\t"
+		    "movq "RB", 8*1(%[state]);\n\t"
+		    "movq "RC", 8*2(%[state]);\n\t"
+		    "movq "RD", 8*3(%[state]);\n\t"
+		    "movq "RE", 8*4(%[state]);\n\t"
+		    "movq "RF", 8*5(%[state]);\n\t"
+		    "movq "RG", 8*6(%[state]);\n\t"
+		    "movq "RH", 8*7(%[state]);\n\t"
+		    :
+		    : [state] "r" (state)
+		    : "memory" );
+
+      nblks--;
+    }
+
+  /* Clear registers */
+  asm volatile ("pxor %%xmm0, %%xmm0;\n\t"
+		"pxor %%xmm1, %%xmm1;\n\t"
+		"pxor %%xmm2, %%xmm2;\n\t"
+		"pxor %%xmm3, %%xmm3;\n\t"
+		"pxor %%xmm4, %%xmm4;\n\t"
+		"pxor %%xmm5, %%xmm5;\n\t"
+		"pxor %%xmm6, %%xmm6;\n\t"
+		"pxor %%mm0, %%mm0;\n\t"
+		"pxor %%mm1, %%mm1;\n\t"
+		"pxor %%mm2, %%mm2;\n\t"
+		"pxor %%mm3, %%mm3;\n\t"
+		"pxor %%mm4, %%mm4;\n\t"
+		"pxor %%mm5, %%mm5;\n\t"
+		"pxor %%mm6, %%mm6;\n\t"
+		"pxor %%mm7, %%mm7;\n\t"
+		"emms;\n\t"
+	       :
+	       :
+	       : "memory" );
+
+  return sizeof(w) + sizeof(u64) * 6;
+}
+
+#if __clang__
+#  pragma clang attribute pop
+#  pragma clang attribute pop
+#endif
+
+#endif
diff --git a/cipher/sha512.c b/cipher/sha512.c
index df9a449c3..b603af8d3 100644
--- a/cipher/sha512.c
+++ b/cipher/sha512.c
@@ -104,6 +104,14 @@
 #endif
 
 
+/* USE_SSSE3_I386 indicates whether to compile with Intel SSSE3/i386 code. */
+#undef USE_SSSE3_I386
+#if defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ >= 4 && \
+    defined(HAVE_GCC_INLINE_ASM_SSSE3)
+# define USE_SSSE3_I386 1
+#endif
+
+
 /* USE_PPC_CRYPTO indicates whether to enable PowerPC vector crypto
  * accelerated code. */
 #undef USE_PPC_CRYPTO
@@ -248,6 +256,20 @@ do_sha512_transform_amd64_avx2(void *ctx, const unsigned char *data,
 }
 #endif
 
+#ifdef USE_SSSE3_I386
+unsigned int _gcry_sha512_transform_i386_ssse3(u64 state[8],
+					       const unsigned char *input_data,
+					       size_t num_blks);
+
+static unsigned int
+do_sha512_transform_i386_ssse3(void *ctx, const unsigned char *data,
+			       size_t nblks)
+{
+  SHA512_CONTEXT *hd = ctx;
+  return _gcry_sha512_transform_i386_ssse3 (&hd->state.h0, data, nblks);
+}
+#endif
+
 
 #ifdef USE_ARM_ASM
 unsigned int _gcry_sha512_transform_arm (SHA512_STATE *hd,
@@ -329,6 +351,10 @@ sha512_init_common (SHA512_CONTEXT *ctx, unsigned int flags)
     ctx->bctx.bwrite = do_sha512_transform_ppc8;
   if ((features & HWF_PPC_VCRYPTO) != 0 && (features & HWF_PPC_ARCH_3_00) != 0)
     ctx->bctx.bwrite = do_sha512_transform_ppc9;
+#endif
+#ifdef USE_SSSE3_I386
+  if ((features & HWF_INTEL_SSSE3) != 0)
+    ctx->bctx.bwrite = do_sha512_transform_i386_ssse3;
 #endif
   (void)features;
 }
diff --git a/configure.ac b/configure.ac
index 75ec82160..4d4fb49aa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2672,6 +2672,10 @@ if test "$found" = "1" ; then
          GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-avx-amd64.lo"
          GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-avx2-bmi2-amd64.lo"
       ;;
+      i?86-*-*)
+         # Build with the assembly implementation
+         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-ssse3-i386.lo"
+      ;;
       arm*-*-*)
          # Build with the assembly implementation
          GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-arm.lo"




More information about the Gcrypt-devel mailing list