>From 21b21748be8218a0a481174bf6a80cbbd749555b Mon Sep 17 00:00:00 2001
From: "Yuriy M. Kaminskiy" <yumkam@gmail.com>
Date: Mon, 11 Mar 2019 21:20:56 +0300
Subject: [PATCH 3/3] chacha-blocks: add (fat) x86/sse2 implementation

Adopted from public domain implementation by Andrew Moon
<liquidsun@gmail.com>
    https://github.com/floodyberry/chacha-opt

Before (AMD K8 @ 2.5GHz):
     STREAM enc |      5.54 ns/B     172.0 MiB/s     13.86 c/B
After:
     STREAM enc |      3.11 ns/B     306.6 MiB/s      7.78 c/B
---
 Makefile.in                  |   3 +-
 configure.ac                 |  11 +
 fat-setup.h                  |   3 +
 fat-x86.c                    | 232 +++++++++++
 x86/chacha_constants_x86.inc |   7 +
 x86/fat/chacha-blocks.asm    |  37 ++
 x86/sse2/chacha-blocks.asm   | 949 +++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 1241 insertions(+), 1 deletion(-)
 create mode 100644 fat-x86.c
 create mode 100644 x86/chacha_constants_x86.inc
 create mode 100644 x86/fat/chacha-blocks.asm
 create mode 100644 x86/sse2/chacha-blocks.asm

diff --git a/Makefile.in b/Makefile.in
index 83250cf3..d1cfc461 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -187,7 +187,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \
 		  ed25519-sha512-pubkey.c \
 		  ed25519-sha512-sign.c ed25519-sha512-verify.c
 
-OPT_SOURCES = fat-x86_64.c fat-arm.c mini-gmp.c
+OPT_SOURCES = fat-x86.c fat-x86_64.c fat-arm.c mini-gmp.c
 
 HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \
 	  base16.h base64.h bignum.h buffer.h camellia.h cast128.h \
@@ -585,6 +585,7 @@ distdir: $(DISTFILES)
 	  fi ; \
 	done
 	set -e; for d in sparc32 sparc64 x86 \
+		x86/fat x86/sse2 \
 		x86_64 x86_64/aesni x86_64/fat \
 		arm arm/neon arm/v6 arm/fat ; do \
 	  mkdir "$(distdir)/$$d" ; \
diff --git a/configure.ac b/configure.ac
index 21c932a5..fd6abbed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -419,6 +419,17 @@ if test "x$enable_assembler" = xyes ; then
 	fi
       else
 	asm_path=x86
+	if test "x$enable_fat" = xyes ; then
+	  asm_path="x86/fat $asm_path"
+	  OPT_NETTLE_SOURCES="fat-x86.c $OPT_NETTLE_SOURCES"
+	else
+	  if test "x$enable_x86_aesni" = xyes ; then
+	    asm_path="x86/aesni $asm_path"
+	  fi
+	  if test "x$enable_x86_sse2" = xyes ; then
+	    asm_path="x86/aesni $asm_path"
+	  fi
+	fi
       fi
       ;;
     *sparc*)
diff --git a/fat-setup.h b/fat-setup.h
index b623ebf9..73c8e7a7 100644
--- a/fat-setup.h
+++ b/fat-setup.h
@@ -176,3 +176,6 @@ typedef void umac_nh_n_func (uint64_t *out, unsigned n, const uint32_t *key,
 			     unsigned length, const uint8_t *msg);
 
 typedef void chacha_core_func(uint32_t *dst, const uint32_t *src, unsigned rounds);
+
+struct chacha_ctx;
+typedef void chacha_blocks_func(struct chacha_ctx *ctx, const uint8_t *src, uint8_t *dst, size_t length, size_t rounds);
diff --git a/fat-x86.c b/fat-x86.c
new file mode 100644
index 00000000..9d4e6bda
--- /dev/null
+++ b/fat-x86.c
@@ -0,0 +1,232 @@
+/* fat-x86_64.c
+
+   Copyright (C) 2015 Niels M��ller
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle 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
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#define _GNU_SOURCE
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nettle-types.h"
+
+#include "aes-internal.h"
+#include "memxor.h"
+#include "fat-setup.h"
+
+#if 0
+void _nettle_cpuid (uint32_t input, uint32_t regs[4]);
+#endif
+
+struct x86_features
+{
+#if 0
+  enum x86_vendor { X86_OTHER, X86_INTEL, X86_AMD } vendor;
+  int have_aesni;
+#endif
+  int have_sse2;
+};
+
+#define SKIP(s, slen, literal, llen)				\
+  (((slen) >= (llen) && memcmp ((s), (literal), llen) == 0)	\
+   ? ((slen) -= (llen), (s) += (llen), 1) : 0)
+#define MATCH(s, slen, literal, llen)				\
+  ((slen) == (llen) && memcmp ((s), (literal), llen) == 0)
+
+static void
+get_x86_features (struct x86_features *features)
+{
+  const char *s;
+#if 0
+  features->vendor = X86_OTHER;
+  features->have_aesni = 0;
+#endif
+  features->have_sse2 = 0;
+
+  s = secure_getenv (ENV_OVERRIDE);
+  if (s)
+    for (;;)
+      {
+	const char *sep = strchr (s, ',');
+	size_t length = sep ? (size_t) (sep - s) : strlen(s);
+
+#if 0
+	if (SKIP (s, length, "vendor:", 7))
+	  {
+	    if (MATCH(s, length, "intel", 5))
+	      features->vendor = X86_INTEL;
+	    else if (MATCH(s, length, "amd", 3))
+	      features->vendor = X86_AMD;
+	    
+	  }
+	else
+	if (MATCH (s, length, "aesni", 5))
+	  features->have_aesni = 1;
+	else
+#endif
+	if (MATCH (s, length, "sse2", 4))
+	  features->have_sse2 = 1;
+	if (!sep)
+	  break;
+	s = sep + 1;	
+      }
+  else
+    {
+#if 0
+      uint32_t cpuid_data[4];
+      _nettle_cpuid (0, cpuid_data);
+      if (memcmp (cpuid_data + 1, "Genu" "ntel" "ineI", 12) == 0)
+	features->vendor = X86_INTEL;
+      else if (memcmp (cpuid_data + 1, "Auth" "cAMD" "enti", 12) == 0)
+	features->vendor = X86_AMD;
+
+      _nettle_cpuid (1, cpuid_data);
+      if (cpuid_data[2] & 0x02000000)
+	features->have_aesni = 1;      
+#endif
+#if __GNUC__ && __GNUC__ >= 6 /* arbitrary */
+      if (__builtin_cpu_supports("sse2"))
+	features->have_sse2 = 1;
+#endif
+    }
+}
+
+#if 0
+DECLARE_FAT_FUNC(_nettle_aes_encrypt, aes_crypt_internal_func)
+DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, x86_64)
+DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, aesni)
+
+DECLARE_FAT_FUNC(_nettle_aes_decrypt, aes_crypt_internal_func)
+DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, x86_64)
+DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, aesni)
+
+DECLARE_FAT_FUNC(nettle_memxor, memxor_func)
+DECLARE_FAT_FUNC_VAR(memxor, memxor_func, x86_64)
+DECLARE_FAT_FUNC_VAR(memxor, memxor_func, sse2)
+#endif
+DECLARE_FAT_FUNC(_nettle_chacha_blocks, chacha_blocks_func)
+DECLARE_FAT_FUNC_VAR(chacha_blocks, chacha_blocks_func, c)
+DECLARE_FAT_FUNC_VAR(chacha_blocks, chacha_blocks_func, sse2)
+
+/* This function should usually be called only once, at startup. But
+   it is idempotent, and on x86, pointer updates are atomic, so
+   there's no danger if it is called simultaneously from multiple
+   threads. */
+static void CONSTRUCTOR
+fat_init (void)
+{
+  struct x86_features features;
+  int verbose;
+
+  /* FIXME: Replace all getenv calls by getenv_secure? */
+  verbose = getenv (ENV_VERBOSE) != NULL;
+  if (verbose)
+    fprintf (stderr, "libnettle: fat library initialization.\n");
+
+  get_x86_features (&features);
+#if 0
+  if (verbose)
+    {
+      const char * const vendor_names[3] =
+	{ "other", "intel", "amd" };
+      fprintf (stderr, "libnettle: cpu features: vendor:%s%s\n",
+	       vendor_names[features.vendor],
+	       features.have_aesni ? ",aesni" : "");
+    }
+  if (features.have_aesni)
+    {
+      if (verbose)
+	fprintf (stderr, "libnettle: using aes instructions.\n");
+      _nettle_aes_encrypt_vec = _nettle_aes_encrypt_aesni;
+      _nettle_aes_decrypt_vec = _nettle_aes_decrypt_aesni;
+    }
+  else
+    {
+      if (verbose)
+	fprintf (stderr, "libnettle: not using aes instructions.\n");
+      _nettle_aes_encrypt_vec = _nettle_aes_encrypt_x86_64;
+      _nettle_aes_decrypt_vec = _nettle_aes_decrypt_x86_64;
+    }
+
+  if (features.vendor == X86_INTEL)
+    {
+      if (verbose)
+	fprintf (stderr, "libnettle: intel SSE2 will be used for memxor.\n");
+      nettle_memxor_vec = _nettle_memxor_sse2;
+    }
+  else
+    {
+      if (verbose)
+	fprintf (stderr, "libnettle: intel SSE2 will not be used for memxor.\n");
+      nettle_memxor_vec = _nettle_memxor_x86_64;
+    }
+#endif
+  if (features.have_sse2)
+    {
+      if (verbose)
+	fprintf (stderr, "libnettle: using sse2 instructions.\n");
+      _nettle_chacha_blocks_vec = _nettle_chacha_blocks_sse2;
+    }
+  else
+    {
+      if (verbose)
+	fprintf (stderr, "libnettle: not using sse2 instructions.\n");
+      _nettle_chacha_blocks_vec = _nettle_chacha_blocks_c;
+    }
+}
+
+#if 0
+DEFINE_FAT_FUNC(_nettle_aes_encrypt, void,
+		(unsigned rounds, const uint32_t *keys,
+		 const struct aes_table *T,
+		 size_t length, uint8_t *dst,
+		 const uint8_t *src),
+		(rounds, keys, T, length, dst, src))
+
+DEFINE_FAT_FUNC(_nettle_aes_decrypt, void,
+		(unsigned rounds, const uint32_t *keys,
+		 const struct aes_table *T,
+		 size_t length, uint8_t *dst,
+		 const uint8_t *src),
+		(rounds, keys, T, length, dst, src))
+
+DEFINE_FAT_FUNC(nettle_memxor, void *,
+		(void *dst, const void *src, size_t n),
+		(dst, src, n))
+#endif
+
+DEFINE_FAT_FUNC(_nettle_chacha_blocks, void,
+		(struct chacha_ctx *ctx, const uint8_t *src, uint8_t *dst, size_t length, size_t rounds),
+		(ctx, src, dst, length, rounds))
diff --git a/x86/chacha_constants_x86.inc b/x86/chacha_constants_x86.inc
new file mode 100644
index 00000000..79b9881b
--- /dev/null
+++ b/x86/chacha_constants_x86.inc
@@ -0,0 +1,7 @@
+.section .rodata
+.p2align 4,,15
+chacha_constants:
+.long 0x61707865,0x3320646e,0x79622d32,0x6b206574 /* "expand 32-byte k" */
+.byte 2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13       /* pshufb rotate by 16 */
+.byte 3,0,1,2,7,4,5,6,11,8,9,10,15,12,13,14       /* pshufb rotate by 8 */
+
diff --git a/x86/fat/chacha-blocks.asm b/x86/fat/chacha-blocks.asm
new file mode 100644
index 00000000..98d5c8a6
--- /dev/null
+++ b/x86/fat/chacha-blocks.asm
@@ -0,0 +1,37 @@
+C x86/fat/chacha-blocks.asm
+
+ifelse(<
+   Copyright (C) 2015 Niels M��ller
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle 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
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+>)
+
+dnl PROLOGUE(_nettle_chacha_blocks) picked up by configure
+dnl PROLOGUE(_nettle_hchacha) picked up by configure
+
+define(<fat_transform>, <$1_sse2>)
+include_src(<x86/sse2/chacha-blocks.asm>)
diff --git a/x86/sse2/chacha-blocks.asm b/x86/sse2/chacha-blocks.asm
new file mode 100644
index 00000000..786db7b7
--- /dev/null
+++ b/x86/sse2/chacha-blocks.asm
@@ -0,0 +1,949 @@
+C x86/chacha-blocks.asm
+
+ifelse(<
+   Copyright (C) 2014 Andrew Moon <liquidsun@gmail.com>
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle 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
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+>)
+
+C This file was released as Public-Domain-or-MIT at
+C https://github.com/floodyberry/chacha-opt
+
+	.file "chacha-blocks.asm"
+
+	C chacha_blocks(struct chacha_ctx *ctx,
+	C               const uint8_t *src, uint8_t *dst, size_t length,
+	C		unsigned rounds)
+	.text
+.macro LOAD_VAR_PIC var, reg
+	call 1f
+	1:
+	popl \reg
+	leal \var - 1b(\reg), \reg
+.endm
+	ALIGN(16)
+chacha_blocks_sse2_local:
+PROLOGUE(_nettle_chacha_blocks)
+.cfi_startproc
+pushl %ebp
+.cfi_adjust_cfa_offset 4
+.cfi_rel_offset %ebp, 0
+.cfi_def_cfa_register %ebp
+	pushl %ebx
+.cfi_adjust_cfa_offset 4
+.cfi_rel_offset %ebx, 0
+	pushl %esi
+.cfi_adjust_cfa_offset 4
+.cfi_rel_offset %esi, 0
+	pushl %edi
+.cfi_adjust_cfa_offset 4
+.cfi_rel_offset %edi, 0
+movl %esp, %ebp
+andl $~63, %esp
+sub $704, %esp
+C movl %ebx,68(%esp)
+C movl %esi,72(%esp
+C movl %edi,76(%esp)
+C movl 8(%ebp),%ecx
+	movl 8+12(%ebp),%ecx
+movl %ecx,84(%esp)
+C movl 12(%ebp),%esi
+	movl 12+12(%ebp),%esi
+C movl 16(%ebp),%edx
+	movl 16+12(%ebp),%edx
+C movl 20(%ebp),%eax
+	movl 20+12(%ebp),%eax
+C LOAD_VAR_PIC chacha_constants, %ebx
+C movdqa 0(%ebx), %xmm0
+C movdqu 0(%ecx),%xmm1
+C movdqu 16(%ecx),%xmm2
+C movdqu 32(%ecx),%xmm3
+	movdqu 0(%ecx), %xmm0
+	movdqu 16(%ecx), %xmm1
+	movdqu 32(%ecx), %xmm2
+	movdqu 48(%ecx), %xmm3
+movdqa %xmm0,0(%esp)
+movdqa %xmm1,16(%esp)
+movdqa %xmm2,32(%esp)
+movdqa %xmm3,48(%esp)
+C movl 48(%ecx),%ecx
+	movl 24+12(%ebp),%ecx
+movl %ecx,88(%esp)
+cmpl $0,%eax
+jbe .Lchacha_blocks_sse2_done
+cmpl $256,%eax
+jb .Lchacha_blocks_sse2_bytesbetween1and255
+pshufd $0x00, %xmm0, %xmm4
+pshufd $0x55, %xmm0, %xmm5
+pshufd $0xaa, %xmm0, %xmm6
+pshufd $0xff, %xmm0, %xmm0
+movdqa %xmm4,128(%esp)
+movdqa %xmm5,144(%esp)
+movdqa %xmm6,160(%esp)
+movdqa %xmm0,176(%esp)
+pshufd $0x00, %xmm1, %xmm0
+pshufd $0x55, %xmm1, %xmm4
+pshufd $0xaa, %xmm1, %xmm5
+pshufd $0xff, %xmm1, %xmm1
+movdqa %xmm0,192(%esp)
+movdqa %xmm4,208(%esp)
+movdqa %xmm5,224(%esp)
+movdqa %xmm1,240(%esp)
+pshufd $0x00, %xmm2, %xmm0
+pshufd $0x55, %xmm2, %xmm1
+pshufd $0xaa, %xmm2, %xmm4
+pshufd $0xff, %xmm2, %xmm2
+movdqa %xmm0,256(%esp)
+movdqa %xmm1,272(%esp)
+movdqa %xmm4,288(%esp)
+movdqa %xmm2,304(%esp)
+pshufd $0xaa, %xmm3, %xmm0
+pshufd $0xff, %xmm3, %xmm1
+movdqa %xmm0,352(%esp)
+movdqa %xmm1,368(%esp)
+.Lchacha_blocks_sse2_bytesatleast256:
+movl 48(%esp),%ecx
+movl 4+48(%esp),%ebx
+movl %ecx,320(%esp)
+movl %ebx,336(%esp)
+addl $1,%ecx
+adcl $0,%ebx
+movl %ecx,4+320(%esp)
+movl %ebx,4+336(%esp)
+addl $1,%ecx
+adcl $0,%ebx
+movl %ecx,8+320(%esp)
+movl %ebx,8+336(%esp)
+addl $1,%ecx
+adcl $0,%ebx
+movl %ecx,12+320(%esp)
+movl %ebx,12+336(%esp)
+addl $1,%ecx
+adcl $0,%ebx
+movl %ecx,48(%esp)
+movl %ebx,4+48(%esp)
+movl %eax,92(%esp)
+movl 88(%esp),%eax
+movdqa 160(%esp),%xmm0
+movdqa 224(%esp),%xmm1
+movdqa 288(%esp),%xmm2
+movdqa 352(%esp),%xmm3
+movdqa 176(%esp),%xmm4
+movdqa 240(%esp),%xmm5
+movdqa 304(%esp),%xmm6
+movdqa 368(%esp),%xmm7
+movdqa %xmm0,480(%esp)
+movdqa %xmm1,544(%esp)
+movdqa %xmm2,608(%esp)
+movdqa %xmm3,672(%esp)
+movdqa %xmm4,496(%esp)
+movdqa %xmm5,560(%esp)
+movdqa %xmm6,624(%esp)
+movdqa %xmm7,688(%esp)
+movdqa 128(%esp),%xmm0
+movdqa 192(%esp),%xmm1
+movdqa 256(%esp),%xmm2
+movdqa 320(%esp),%xmm3
+movdqa 144(%esp),%xmm4
+movdqa 208(%esp),%xmm5
+movdqa 272(%esp),%xmm6
+movdqa 336(%esp),%xmm7
+jmp .Lchacha_blocks_sse2_mainloop1
+.p2align 6
+.Lchacha_blocks_sse2_mainloop1:
+paddd %xmm1, %xmm0
+paddd %xmm5, %xmm4
+pxor %xmm0, %xmm3
+pxor %xmm4, %xmm7
+pshuflw $0xb1,%xmm3,%xmm3
+pshuflw $0xb1,%xmm7,%xmm7
+pshufhw $0xb1,%xmm3,%xmm3
+pshufhw $0xb1,%xmm7,%xmm7
+movdqa %xmm4, 464(%esp)
+paddd %xmm3, %xmm2
+paddd %xmm7, %xmm6
+pxor %xmm2, %xmm1
+pxor %xmm6, %xmm5
+movdqa %xmm1, %xmm4
+pslld $12, %xmm1
+psrld $20, %xmm4
+por %xmm4, %xmm1
+movdqa %xmm5, %xmm4
+pslld $12, %xmm5
+psrld $20, %xmm4
+por %xmm4, %xmm5
+movdqa 464(%esp), %xmm4
+paddd %xmm1, %xmm0
+paddd %xmm5, %xmm4
+pxor %xmm0, %xmm3
+pxor %xmm4, %xmm7
+movdqa %xmm0, 448(%esp)
+movdqa %xmm4, 464(%esp)
+movdqa %xmm3, %xmm4
+pslld $8, %xmm3
+psrld $24, %xmm4
+por %xmm4, %xmm3
+movdqa %xmm7, %xmm4
+pslld $8, %xmm7
+psrld $24, %xmm4
+por %xmm4, %xmm7
+paddd %xmm3, %xmm2
+paddd %xmm7, %xmm6
+movdqa %xmm3, 640(%esp)
+movdqa %xmm7, 656(%esp)
+pxor %xmm2, %xmm1
+pxor %xmm6, %xmm5
+movdqa %xmm2, 576(%esp)
+movdqa %xmm6, 592(%esp)
+movdqa %xmm1,%xmm4
+pslld $7, %xmm1
+movdqa 672(%esp), %xmm3
+psrld $25, %xmm4
+movdqa 688(%esp), %xmm7
+por %xmm4, %xmm1
+movdqa %xmm1, 512(%esp)
+movdqa %xmm5, %xmm0
+pslld $7, %xmm5
+movdqa 608(%esp), %xmm2
+psrld $25, %xmm0
+movdqa 624(%esp), %xmm6
+por %xmm0, %xmm5
+movdqa %xmm5, 528(%esp)
+movdqa 480(%esp), %xmm0
+movdqa 496(%esp), %xmm4
+movdqa 544(%esp), %xmm1
+movdqa 560(%esp), %xmm5
+paddd %xmm1, %xmm0
+paddd %xmm5, %xmm4
+pxor %xmm0, %xmm3
+pxor %xmm4, %xmm7
+pshuflw $0xb1,%xmm3,%xmm3
+pshuflw $0xb1,%xmm7,%xmm7
+pshufhw $0xb1,%xmm3,%xmm3
+pshufhw $0xb1,%xmm7,%xmm7
+movdqa %xmm4, 496(%esp)
+paddd %xmm3, %xmm2
+paddd %xmm7, %xmm6
+pxor %xmm2, %xmm1
+pxor %xmm6, %xmm5
+movdqa %xmm1, %xmm4
+pslld $12, %xmm1
+psrld $20, %xmm4
+por %xmm4, %xmm1
+movdqa %xmm5, %xmm4
+pslld $12, %xmm5
+psrld $20, %xmm4
+por %xmm4, %xmm5
+movdqa 496(%esp), %xmm4
+paddd %xmm1, %xmm0
+paddd %xmm5, %xmm4
+pxor %xmm0, %xmm3
+pxor %xmm4, %xmm7
+movdqa %xmm0, 480(%esp)
+movdqa %xmm4, 496(%esp)
+movdqa %xmm3, %xmm4
+pslld $8, %xmm3
+psrld $24, %xmm4
+por %xmm4, %xmm3
+movdqa %xmm7, %xmm4
+pslld $8, %xmm7
+psrld $24, %xmm4
+por %xmm4, %xmm7
+paddd %xmm3, %xmm2
+paddd %xmm7, %xmm6
+movdqa %xmm3, 672(%esp)
+pxor %xmm2, %xmm1
+pxor %xmm6, %xmm5
+movdqa %xmm1,%xmm4
+pslld $7, %xmm1
+psrld $25, %xmm4
+movdqa 640(%esp), %xmm3
+por %xmm4, %xmm1
+movdqa %xmm5, %xmm0
+pslld $7, %xmm5
+psrld $25, %xmm0
+por %xmm0, %xmm5
+movdqa %xmm5, 560(%esp)
+movdqa 448(%esp), %xmm0
+movdqa 528(%esp), %xmm5
+movdqa 464(%esp), %xmm4
+paddd %xmm5, %xmm0
+paddd %xmm1, %xmm4
+pxor %xmm0, %xmm7
+pxor %xmm4, %xmm3
+pshuflw $0xb1,%xmm7,%xmm7
+pshuflw $0xb1,%xmm3,%xmm3
+pshufhw $0xb1,%xmm7,%xmm7
+pshufhw $0xb1,%xmm3,%xmm3
+movdqa %xmm4, 464(%esp)
+paddd %xmm7, %xmm2
+paddd %xmm3, %xmm6
+pxor %xmm2, %xmm5
+pxor %xmm6, %xmm1
+movdqa %xmm5, %xmm4
+pslld $12, %xmm5
+psrld $20, %xmm4
+por %xmm4, %xmm5
+movdqa %xmm1, %xmm4
+pslld $12, %xmm1
+psrld $20, %xmm4
+por %xmm4, %xmm1
+movdqa 464(%esp), %xmm4
+paddd %xmm5, %xmm0
+paddd %xmm1, %xmm4
+pxor %xmm0, %xmm7
+pxor %xmm4, %xmm3
+movdqa %xmm0, 448(%esp)
+movdqa %xmm4, 464(%esp)
+movdqa %xmm7, %xmm4
+pslld $8, %xmm7
+psrld $24, %xmm4
+por %xmm4, %xmm7
+movdqa %xmm3, %xmm4
+pslld $8, %xmm3
+psrld $24, %xmm4
+por %xmm4, %xmm3
+paddd %xmm7, %xmm2
+paddd %xmm3, %xmm6
+movdqa %xmm7, 688(%esp)
+movdqa %xmm3, 640(%esp)
+pxor %xmm2, %xmm5
+pxor %xmm6, %xmm1
+movdqa %xmm2, 608(%esp)
+movdqa %xmm6, 624(%esp)
+movdqa %xmm5,%xmm4
+pslld $7, %xmm5
+movdqa 656(%esp), %xmm7
+psrld $25, %xmm4
+movdqa 672(%esp), %xmm3
+por %xmm4, %xmm5
+movdqa %xmm5, 528(%esp)
+movdqa %xmm1, %xmm0
+pslld $7, %xmm1
+movdqa 576(%esp), %xmm2
+psrld $25, %xmm0
+movdqa 592(%esp), %xmm6
+por %xmm0, %xmm1
+movdqa %xmm1, 544(%esp)
+movdqa 480(%esp), %xmm0
+movdqa 496(%esp), %xmm4
+movdqa 560(%esp), %xmm5
+movdqa 512(%esp), %xmm1
+paddd %xmm5, %xmm0
+paddd %xmm1, %xmm4
+pxor %xmm0, %xmm7
+pxor %xmm4, %xmm3
+pshuflw $0xb1,%xmm7,%xmm7
+pshuflw $0xb1,%xmm3,%xmm3
+pshufhw $0xb1,%xmm7,%xmm7
+pshufhw $0xb1,%xmm3,%xmm3
+movdqa %xmm4, 496(%esp)
+paddd %xmm7, %xmm2
+paddd %xmm3, %xmm6
+pxor %xmm2, %xmm5
+pxor %xmm6, %xmm1
+movdqa %xmm5, %xmm4
+pslld $12, %xmm5
+psrld $20, %xmm4
+por %xmm4, %xmm5
+movdqa %xmm1, %xmm4
+pslld $12, %xmm1
+psrld $20, %xmm4
+por %xmm4, %xmm1
+movdqa 496(%esp), %xmm4
+paddd %xmm5, %xmm0
+paddd %xmm1, %xmm4
+pxor %xmm0, %xmm7
+pxor %xmm4, %xmm3
+movdqa %xmm0, 480(%esp)
+movdqa %xmm4, 496(%esp)
+movdqa %xmm7, %xmm4
+pslld $8, %xmm7
+psrld $24, %xmm4
+por %xmm4, %xmm7
+movdqa %xmm3, %xmm4
+pslld $8, %xmm3
+psrld $24, %xmm4
+por %xmm4, %xmm3
+paddd %xmm7, %xmm2
+paddd %xmm3, %xmm6
+movdqa %xmm3, 672(%esp)
+pxor %xmm2, %xmm5
+pxor %xmm6, %xmm1
+movdqa %xmm5,%xmm4
+pslld $7, %xmm5
+psrld $25, %xmm4
+movdqa 640(%esp), %xmm3
+por %xmm4, %xmm5
+movdqa %xmm5, 560(%esp)
+movdqa %xmm1, %xmm0
+pslld $7, %xmm1
+psrld $25, %xmm0
+por %xmm0, %xmm1
+movdqa 448(%esp), %xmm0
+movdqa 464(%esp), %xmm4
+movdqa 528(%esp), %xmm5
+subl $2,%eax
+ja .Lchacha_blocks_sse2_mainloop1
+movdqa %xmm0, 448(%esp)
+movdqa %xmm1, 512(%esp)
+movdqa %xmm2, 576(%esp)
+movdqa %xmm3, 640(%esp)
+movdqa %xmm4, 464(%esp)
+movdqa %xmm5, 528(%esp)
+movdqa %xmm6, 592(%esp)
+movdqa %xmm7, 656(%esp)
+cmpl $0,%esi
+movdqa 448(%esp),%xmm0
+movdqa 464(%esp),%xmm1
+movdqa 480(%esp),%xmm2
+movdqa 496(%esp),%xmm3
+paddd 128(%esp), %xmm0
+paddd 144(%esp), %xmm1
+paddd 160(%esp), %xmm2
+paddd 176(%esp), %xmm3
+movdqa %xmm0, %xmm4
+movdqa %xmm2, %xmm5
+punpckldq %xmm1, %xmm4
+punpckldq %xmm3, %xmm5
+punpckhdq %xmm1, %xmm0
+punpckhdq %xmm3, %xmm2
+movdqa %xmm4, %xmm1
+movdqa %xmm0, %xmm3
+punpcklqdq %xmm5, %xmm4
+punpckhqdq %xmm5, %xmm1
+punpcklqdq %xmm2, %xmm0
+punpckhqdq %xmm2, %xmm3
+jbe .Lchacha_blocks_sse2_noinput1
+movdqu 0(%esi), %xmm2
+movdqu 64(%esi), %xmm5
+movdqu 128(%esi), %xmm6
+movdqu 192(%esi), %xmm7
+pxor %xmm2, %xmm4
+pxor %xmm5, %xmm1
+pxor %xmm6, %xmm0
+pxor %xmm7, %xmm3
+movdqu %xmm4, 0(%edx)
+movdqu %xmm1, 64(%edx)
+movdqu %xmm0, 128(%edx)
+movdqu %xmm3, 192(%edx)
+movdqa 512(%esp),%xmm0
+movdqa 528(%esp),%xmm1
+movdqa 544(%esp),%xmm2
+movdqa 560(%esp),%xmm3
+paddd 192(%esp), %xmm0
+paddd 208(%esp), %xmm1
+paddd 224(%esp), %xmm2
+paddd 240(%esp), %xmm3
+movdqa %xmm0, %xmm4
+movdqa %xmm2, %xmm5
+punpckldq %xmm1, %xmm4
+punpckldq %xmm3, %xmm5
+punpckhdq %xmm1, %xmm0
+punpckhdq %xmm3, %xmm2
+movdqa %xmm4, %xmm1
+movdqa %xmm0, %xmm3
+punpcklqdq %xmm5, %xmm4
+punpckhqdq %xmm5, %xmm1
+punpcklqdq %xmm2, %xmm0
+punpckhqdq %xmm2, %xmm3
+movdqu 16+0(%esi), %xmm2
+movdqu 16+64(%esi), %xmm5
+movdqu 16+128(%esi), %xmm6
+movdqu 16+192(%esi), %xmm7
+pxor %xmm2, %xmm4
+pxor %xmm5, %xmm1
+pxor %xmm6, %xmm0
+pxor %xmm7, %xmm3
+movdqu %xmm4, 16+0(%edx)
+movdqu %xmm1, 16+64(%edx)
+movdqu %xmm0, 16+128(%edx)
+movdqu %xmm3, 16+192(%edx)
+movdqa 576(%esp),%xmm0
+movdqa 592(%esp),%xmm1
+movdqa 608(%esp),%xmm2
+movdqa 624(%esp),%xmm3
+paddd 256(%esp), %xmm0
+paddd 272(%esp), %xmm1
+paddd 288(%esp), %xmm2
+paddd 304(%esp), %xmm3
+movdqa %xmm0, %xmm4
+movdqa %xmm2, %xmm5
+punpckldq %xmm1, %xmm4
+punpckldq %xmm3, %xmm5
+punpckhdq %xmm1, %xmm0
+punpckhdq %xmm3, %xmm2
+movdqa %xmm4, %xmm1
+movdqa %xmm0, %xmm3
+punpcklqdq %xmm5, %xmm4
+punpckhqdq %xmm5, %xmm1
+punpcklqdq %xmm2, %xmm0
+punpckhqdq %xmm2, %xmm3
+movdqu 32+0(%esi), %xmm2
+movdqu 32+64(%esi), %xmm5
+movdqu 32+128(%esi), %xmm6
+movdqu 32+192(%esi), %xmm7
+pxor %xmm2, %xmm4
+pxor %xmm5, %xmm1
+pxor %xmm6, %xmm0
+pxor %xmm7, %xmm3
+movdqu %xmm4, 32+0(%edx)
+movdqu %xmm1, 32+64(%edx)
+movdqu %xmm0, 32+128(%edx)
+movdqu %xmm3, 32+192(%edx)
+movdqa 640(%esp),%xmm0
+movdqa 656(%esp),%xmm1
+movdqa 672(%esp),%xmm2
+movdqa 688(%esp),%xmm3
+paddd 320(%esp), %xmm0
+paddd 336(%esp), %xmm1
+paddd 352(%esp), %xmm2
+paddd 368(%esp), %xmm3
+movdqa %xmm0, %xmm4
+movdqa %xmm2, %xmm5
+punpckldq %xmm1, %xmm4
+punpckldq %xmm3, %xmm5
+punpckhdq %xmm1, %xmm0
+punpckhdq %xmm3, %xmm2
+movdqa %xmm4, %xmm1
+movdqa %xmm0, %xmm3
+punpcklqdq %xmm5, %xmm4
+punpckhqdq %xmm5, %xmm1
+punpcklqdq %xmm2, %xmm0
+punpckhqdq %xmm2, %xmm3
+movdqu 48+0(%esi), %xmm2
+movdqu 48+64(%esi), %xmm5
+movdqu 48+128(%esi), %xmm6
+movdqu 48+192(%esi), %xmm7
+pxor %xmm2, %xmm4
+pxor %xmm5, %xmm1
+pxor %xmm6, %xmm0
+pxor %xmm7, %xmm3
+movdqu %xmm4, 48+0(%edx)
+movdqu %xmm1, 48+64(%edx)
+movdqu %xmm0, 48+128(%edx)
+movdqu %xmm3, 48+192(%edx)
+addl $256,%esi
+jmp .Lchacha_blocks_sse2_mainloop1_cont
+.Lchacha_blocks_sse2_noinput1:
+movdqu %xmm4, 0(%edx)
+movdqu %xmm1, 64(%edx)
+movdqu %xmm0, 128(%edx)
+movdqu %xmm3, 192(%edx)
+movdqa 512(%esp),%xmm0
+movdqa 528(%esp),%xmm1
+movdqa 544(%esp),%xmm2
+movdqa 560(%esp),%xmm3
+paddd 192(%esp), %xmm0
+paddd 208(%esp), %xmm1
+paddd 224(%esp), %xmm2
+paddd 240(%esp), %xmm3
+movdqa %xmm0, %xmm4
+movdqa %xmm2, %xmm5
+punpckldq %xmm1, %xmm4
+punpckldq %xmm3, %xmm5
+punpckhdq %xmm1, %xmm0
+punpckhdq %xmm3, %xmm2
+movdqa %xmm4, %xmm1
+movdqa %xmm0, %xmm3
+punpcklqdq %xmm5, %xmm4
+punpckhqdq %xmm5, %xmm1
+punpcklqdq %xmm2, %xmm0
+punpckhqdq %xmm2, %xmm3
+movdqu %xmm4, 16+0(%edx)
+movdqu %xmm1, 16+64(%edx)
+movdqu %xmm0, 16+128(%edx)
+movdqu %xmm3, 16+192(%edx)
+movdqa 576(%esp),%xmm0
+movdqa 592(%esp),%xmm1
+movdqa 608(%esp),%xmm2
+movdqa 624(%esp),%xmm3
+paddd 256(%esp), %xmm0
+paddd 272(%esp), %xmm1
+paddd 288(%esp), %xmm2
+paddd 304(%esp), %xmm3
+movdqa %xmm0, %xmm4
+movdqa %xmm2, %xmm5
+punpckldq %xmm1, %xmm4
+punpckldq %xmm3, %xmm5
+punpckhdq %xmm1, %xmm0
+punpckhdq %xmm3, %xmm2
+movdqa %xmm4, %xmm1
+movdqa %xmm0, %xmm3
+punpcklqdq %xmm5, %xmm4
+punpckhqdq %xmm5, %xmm1
+punpcklqdq %xmm2, %xmm0
+punpckhqdq %xmm2, %xmm3
+movdqu %xmm4, 32+0(%edx)
+movdqu %xmm1, 32+64(%edx)
+movdqu %xmm0, 32+128(%edx)
+movdqu %xmm3, 32+192(%edx)
+movdqa 640(%esp),%xmm0
+movdqa 656(%esp),%xmm1
+movdqa 672(%esp),%xmm2
+movdqa 688(%esp),%xmm3
+paddd 320(%esp), %xmm0
+paddd 336(%esp), %xmm1
+paddd 352(%esp), %xmm2
+paddd 368(%esp), %xmm3
+movdqa %xmm0, %xmm4
+movdqa %xmm2, %xmm5
+punpckldq %xmm1, %xmm4
+punpckldq %xmm3, %xmm5
+punpckhdq %xmm1, %xmm0
+punpckhdq %xmm3, %xmm2
+movdqa %xmm4, %xmm1
+movdqa %xmm0, %xmm3
+punpcklqdq %xmm5, %xmm4
+punpckhqdq %xmm5, %xmm1
+punpcklqdq %xmm2, %xmm0
+punpckhqdq %xmm2, %xmm3
+movdqu %xmm4, 48+0(%edx)
+movdqu %xmm1, 48+64(%edx)
+movdqu %xmm0, 48+128(%edx)
+movdqu %xmm3, 48+192(%edx)
+.Lchacha_blocks_sse2_mainloop1_cont:
+movl 92(%esp),%eax
+subl $256,%eax
+addl $256,%edx
+cmpl $256,%eax
+jae .Lchacha_blocks_sse2_bytesatleast256
+cmpl $0,%eax
+jbe .Lchacha_blocks_sse2_done
+.Lchacha_blocks_sse2_bytesbetween1and255:
+cmpl $64,%eax
+jae .Lchacha_blocks_sse2_nocopy
+movl %edx,92(%esp)
+cmpl $0,%esi
+jbe .Lchacha_blocks_sse2_noinput2
+leal 128(%esp),%edi
+movl %eax,%ecx
+rep movsb
+leal 128(%esp),%esi
+.Lchacha_blocks_sse2_noinput2:
+leal 128(%esp),%edx
+.Lchacha_blocks_sse2_nocopy:
+movl %eax,80(%esp)
+movdqa 0(%esp),%xmm0
+movdqa 16(%esp),%xmm1
+movdqa 32(%esp),%xmm2
+movdqa 48(%esp),%xmm3
+movl 88(%esp),%eax
+.Lchacha_blocks_sse2_mainloop2:
+paddd %xmm1, %xmm0
+pxor %xmm0, %xmm3
+pshuflw $0xb1,%xmm3,%xmm3
+pshufhw $0xb1,%xmm3,%xmm3
+paddd %xmm3, %xmm2
+pxor %xmm2, %xmm1
+movdqa %xmm1,%xmm4
+pslld $12, %xmm1
+psrld $20, %xmm4
+pxor %xmm4, %xmm1
+paddd %xmm1, %xmm0
+pxor %xmm0, %xmm3
+movdqa %xmm3,%xmm4
+pslld $8, %xmm3
+psrld $24, %xmm4
+pshufd $0x93,%xmm0,%xmm0
+pxor %xmm4, %xmm3
+paddd %xmm3, %xmm2
+pshufd $0x4e,%xmm3,%xmm3
+pxor %xmm2, %xmm1
+pshufd $0x39,%xmm2,%xmm2
+movdqa %xmm1,%xmm4
+pslld $7, %xmm1
+psrld $25, %xmm4
+pxor %xmm4, %xmm1
+subl $2, %eax
+paddd %xmm1, %xmm0
+pxor %xmm0, %xmm3
+pshuflw $0xb1,%xmm3,%xmm3
+pshufhw $0xb1,%xmm3,%xmm3
+paddd %xmm3, %xmm2
+pxor %xmm2, %xmm1
+movdqa %xmm1,%xmm4
+pslld $12, %xmm1
+psrld $20, %xmm4
+pxor %xmm4, %xmm1
+paddd %xmm1, %xmm0
+pxor %xmm0, %xmm3
+movdqa %xmm3,%xmm4
+pslld $8, %xmm3
+psrld $24, %xmm4
+pshufd $0x39,%xmm0,%xmm0
+pxor %xmm4, %xmm3
+paddd %xmm3, %xmm2
+pshufd $0x4e,%xmm3,%xmm3
+pxor %xmm2, %xmm1
+pshufd $0x93,%xmm2,%xmm2
+movdqa %xmm1,%xmm4
+pslld $7, %xmm1
+psrld $25, %xmm4
+pxor %xmm4, %xmm1
+ja .Lchacha_blocks_sse2_mainloop2
+paddd 0(%esp), %xmm0
+paddd 16(%esp), %xmm1
+paddd 32(%esp), %xmm2
+paddd 48(%esp), %xmm3
+cmpl $0,%esi
+jbe .Lchacha_blocks_sse2_noinput3
+movdqu 0(%esi),%xmm4
+movdqu 16(%esi),%xmm5
+movdqu 32(%esi),%xmm6
+movdqu 48(%esi),%xmm7
+pxor %xmm4, %xmm0
+pxor %xmm5, %xmm1
+pxor %xmm6, %xmm2
+pxor %xmm7, %xmm3
+addl $64,%esi
+.Lchacha_blocks_sse2_noinput3:
+movdqu %xmm0,0(%edx)
+movdqu %xmm1,16(%edx)
+movdqu %xmm2,32(%edx)
+movdqu %xmm3,48(%edx)
+movl 80(%esp),%eax
+movl 48(%esp),%ecx
+movl 4+48(%esp),%ebx
+addl $1,%ecx
+adcl $0,%ebx
+movl %ecx,48(%esp)
+movl %ebx,4+48(%esp)
+cmpl $64,%eax
+ja .Lchacha_blocks_sse2_bytesatleast65
+jae .Lchacha_blocks_sse2_bytesatleast64
+movl %edx,%esi
+movl 92(%esp),%edi
+movl %eax,%ecx
+rep movsb
+.Lchacha_blocks_sse2_bytesatleast64:
+.Lchacha_blocks_sse2_done:
+movl 84(%esp),%eax
+movdqa 48(%esp),%xmm0
+C movdqu %xmm0,32(%eax)
+	movdqu %xmm0,48(%eax)
+movl 64(%esp),%eax
+C movl 68(%esp),%ebx
+C movl 72(%esp),%esi
+C movl 76(%esp),%edi
+.cfi_remember_state
+movl %ebp, %esp
+.cfi_def_cfa_register %esp
+	popl %edi
+.cfi_adjust_cfa_offset -4
+.cfi_restore %edi
+	popl %esi
+.cfi_adjust_cfa_offset -4
+.cfi_restore %esi
+	popl %ebx
+.cfi_adjust_cfa_offset -4
+.cfi_restore %ebx
+popl %ebp
+.cfi_adjust_cfa_offset -4
+.cfi_restore %ebp
+ret
+.cfi_restore_state
+.Lchacha_blocks_sse2_bytesatleast65:
+subl $64,%eax
+addl $64,%edx
+jmp .Lchacha_blocks_sse2_bytesbetween1and255
+.cfi_endproc
+EPILOGUE(_nettle_chacha_blocks)
+
+
+hchacha_sse2_local:
+PROLOGUE(_nettle_hchacha)
+.cfi_startproc
+LOAD_VAR_PIC chacha_constants, %eax
+movdqa 0(%eax), %xmm0
+movl 4(%esp), %eax
+movl 8(%esp), %edx
+movdqu 0(%eax), %xmm1
+movdqu 16(%eax), %xmm2
+movdqu 0(%edx), %xmm3
+movl 12(%esp), %edx
+movl 16(%esp), %ecx
+.Lhchacha_sse2_mainloop: 
+paddd %xmm1, %xmm0
+pxor %xmm0, %xmm3
+pshuflw $0xb1,%xmm3,%xmm3
+pshufhw $0xb1,%xmm3,%xmm3
+paddd %xmm3, %xmm2
+pxor %xmm2, %xmm1
+movdqa %xmm1,%xmm4
+pslld $12, %xmm1
+psrld $20, %xmm4
+pxor %xmm4, %xmm1
+paddd %xmm1, %xmm0
+pxor %xmm0, %xmm3
+movdqa %xmm3,%xmm4
+pslld $8, %xmm3
+psrld $24, %xmm4
+pshufd $0x93,%xmm0,%xmm0
+pxor %xmm4, %xmm3
+paddd %xmm3, %xmm2
+pshufd $0x4e,%xmm3,%xmm3
+pxor %xmm2, %xmm1
+pshufd $0x39,%xmm2,%xmm2
+movdqa %xmm1,%xmm4
+pslld $7, %xmm1
+psrld $25, %xmm4
+pxor %xmm4, %xmm1
+subl $2, %ecx
+paddd %xmm1, %xmm0
+pxor %xmm0, %xmm3
+pshuflw $0xb1,%xmm3,%xmm3
+pshufhw $0xb1,%xmm3,%xmm3
+paddd %xmm3, %xmm2
+pxor %xmm2, %xmm1
+movdqa %xmm1,%xmm4
+pslld $12, %xmm1
+psrld $20, %xmm4
+pxor %xmm4, %xmm1
+paddd %xmm1, %xmm0
+pxor %xmm0, %xmm3
+movdqa %xmm3,%xmm4
+pslld $8, %xmm3
+psrld $24, %xmm4
+pshufd $0x39,%xmm0,%xmm0
+pxor %xmm4, %xmm3
+paddd %xmm3, %xmm2
+pshufd $0x4e,%xmm3,%xmm3
+pxor %xmm2, %xmm1
+pshufd $0x93,%xmm2,%xmm2
+movdqa %xmm1,%xmm4
+pslld $7, %xmm1
+psrld $25, %xmm4
+pxor %xmm4, %xmm1
+ja .Lhchacha_sse2_mainloop
+movdqu %xmm0, 0(%edx)
+movdqu %xmm3, 16(%edx)
+ret
+.cfi_endproc
+EPILOGUE(_nettle_hchacha)
+
+PROLOGUE(_nettle_chacha)
+.cfi_startproc
+pushl %ebp
+.cfi_adjust_cfa_offset 4
+.cfi_rel_offset %ebp, 0
+pushl %ebx
+.cfi_adjust_cfa_offset 4
+.cfi_rel_offset %ebx, 0
+movl %esp, %ebp
+.cfi_def_cfa_register %ebp
+subl $64, %esp
+andl $~63, %esp
+movl %esp, %ebx
+movl 12(%ebp), %ecx
+xorl %edx, %edx
+movdqu 0(%ecx), %xmm0
+movdqu 16(%ecx), %xmm1
+movdqa %xmm0, 0(%ebx)
+movdqa %xmm1, 16(%ebx)
+movl 16(%ebp), %ecx
+movl %edx, 32(%ebx)
+movl %edx, 36(%ebx)
+movl 0(%ecx), %eax
+movl 4(%ecx), %edx
+movl %eax, 40(%ebx)
+movl %edx, 44(%ebx)
+movl 32(%ebp), %eax
+movl %eax, 48(%ebx)
+pushl 28(%ebp)
+pushl 24(%ebp)
+pushl 20(%ebp)
+pushl %ebx
+call chacha_blocks_sse2_local
+pxor %xmm0, %xmm0
+movdqa %xmm0, 0(%ebx)
+movdqa %xmm0, 16(%ebx)
+movdqa %xmm0, 32(%ebx)
+movl %ebp, %esp
+.cfi_def_cfa_register %esp
+popl %ebx
+.cfi_adjust_cfa_offset -4
+.cfi_restore %ebx
+popl %ebp
+.cfi_adjust_cfa_offset -4
+.cfi_restore %ebp
+ret
+.cfi_endproc
+EPILOGUE(_nettle_chacha)
+
+PROLOGUE(_nettle_xchacha)
+.cfi_startproc
+pushl %ebp
+.cfi_adjust_cfa_offset 4
+.cfi_rel_offset %ebp, 0
+pushl %ebx
+.cfi_adjust_cfa_offset 4
+.cfi_rel_offset %ebx, 0
+movl %esp, %ebp
+.cfi_def_cfa_register %ebp
+subl $64, %esp
+andl $~63, %esp
+movl %esp, %ebx
+pushl 32(%ebp)
+pushl %ebx
+pushl 16(%ebp)
+pushl 12(%ebp)
+call hchacha_sse2_local
+xorl %edx, %edx
+movl 16(%ebp), %ecx
+movl 32(%ebx), %edx
+movl 36(%ebx), %edx
+movl 16(%ecx), %eax
+movl %eax, 40(%ebx)
+movl 20(%ecx), %eax
+movl %eax, 44(%ebx)
+C movl 32(%ebp), %eax
+C movl %eax, 48(%ebx)
+	pushl 32(%ebp)
+pushl 28(%ebp)
+pushl 24(%ebp)
+pushl 20(%ebp)
+pushl %ebx
+call chacha_blocks_sse2_local
+pxor %xmm0, %xmm0
+movdqa %xmm0, 0(%ebx)
+movdqa %xmm0, 16(%ebx)
+movdqa %xmm0, 32(%ebx)
+movl %ebp, %esp
+.cfi_def_cfa_register %esp
+popl %ebx
+.cfi_adjust_cfa_offset -4
+.cfi_restore %ebx
+popl %ebp
+.cfi_adjust_cfa_offset -4
+.cfi_restore %ebp
+ret
+.cfi_endproc
+EPILOGUE(_nettle_xchacha)
+
+include_src(<x86/chacha_constants_x86.inc>)
+
-- 
2.11.0

