[PATCH 3/3] chacha20: add AVX2/AMD64 assembly implementation

Jussi Kivilinna jussi.kivilinna at iki.fi
Sat May 3 19:26:09 CEST 2014


* cipher/Makefile.am: Add 'chacha20-avx2-amd64.S'.
* cipher/chacha20-avx2-amd64.S: New.
* cipher/chacha20.c (USE_AVX2): New macro.
(CHACHA20_context_s): Add 'use_avx2'.
[USE_AVX2] (_gcry_chacha20_amd64_avx2_blocks, chacha20_core_avx2): New.
(chacha20_do_setkey): Check HW features for AVX2.
(chacha20_do_encrypt_stream) [USE_AVX2]: Use AVX2 optimized
implementation, if enabled.
(selftest): Increase size of buf by 256.
* configure.ac [host=x86-64]: Add 'chacha20-avx2-amd64.lo'.
--

Add AVX2 optimized implementation for ChaCha20. Based on implementation by
Andrew Moon.

SSSE3 (Intel Haswell):

 CHACHA20       |  nanosecs/byte   mebibytes/sec   cycles/byte
     STREAM enc |     0.742 ns/B    1284.8 MiB/s      2.38 c/B
     STREAM dec |     0.741 ns/B    1286.5 MiB/s      2.37 c/B

AVX2:

 CHACHA20       |  nanosecs/byte   mebibytes/sec   cycles/byte
     STREAM enc |     0.393 ns/B    2428.0 MiB/s      1.26 c/B
     STREAM dec |     0.392 ns/B    2433.6 MiB/s      1.25 c/B

Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 cipher/Makefile.am           |    2 
 cipher/chacha20-avx2-amd64.S |  950 ++++++++++++++++++++++++++++++++++++++++++
 cipher/chacha20.c            |   38 ++
 configure.ac                 |    1 
 4 files changed, 989 insertions(+), 2 deletions(-)
 create mode 100644 cipher/chacha20-avx2-amd64.S

diff --git a/cipher/Makefile.am b/cipher/Makefile.am
index 27ca7ac..26d13d2 100644
--- a/cipher/Makefile.am
+++ b/cipher/Makefile.am
@@ -59,7 +59,7 @@ EXTRA_libcipher_la_SOURCES = \
 arcfour.c arcfour-amd64.S \
 blowfish.c blowfish-amd64.S blowfish-arm.S \
 cast5.c cast5-amd64.S cast5-arm.S \
-chacha20.c chacha20-ssse3-amd64.S \
+chacha20.c chacha20-ssse3-amd64.S chacha20-avx2-amd64.S \
 crc.c \
 des.c des-amd64.S \
 dsa.c \
diff --git a/cipher/chacha20-avx2-amd64.S b/cipher/chacha20-avx2-amd64.S
new file mode 100644
index 0000000..8a08725
--- /dev/null
+++ b/cipher/chacha20-avx2-amd64.S
@@ -0,0 +1,950 @@
+/* chacha20-avx2-amd64.S  -  AMD64/AVX2 implementation of ChaCha20
+ *
+ * Copyright (C) 2014 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/>.
+ */
+
+/*
+ * Based on public domain implementation by Andrew Moon at
+ *  https://github.com/floodyberry/chacha-opt
+ */
+
+#ifdef __x86_64__
+#include <config.h>
+
+#if defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && \
+    defined(HAVE_GCC_INLINE_ASM_AVX2) && USE_CHACHA20
+
+#ifdef __PIC__
+#  define RIP (%rip)
+#else
+#  define RIP
+#endif
+
+.text
+
+.align 8
+.globl _gcry_chacha20_amd64_avx2_blocks
+.type  _gcry_chacha20_amd64_avx2_blocks, at function;
+_gcry_chacha20_amd64_avx2_blocks:
+.Lchacha_blocks_avx2_local:
+	pushq %rbx
+	pushq %rbp
+	pushq %r12
+	pushq %r13
+	pushq %r14
+	movq %rsp, %rbp
+	andq $~63, %rsp
+	subq $512, %rsp
+	leaq .LC RIP, %rax
+	vmovdqu 0(%rax), %xmm6
+	vmovdqu 16(%rax), %xmm7
+	vmovdqu 0(%rdi), %xmm8
+	vmovdqu 16(%rdi), %xmm9
+	vmovdqu 32(%rdi), %xmm10
+	vmovdqu 48(%rdi), %xmm11
+	movl $20, %eax
+	movq $1, %r9
+	vmovdqa %xmm8, 0(%rsp)
+	vmovdqa %xmm9, 16(%rsp)
+	vmovdqa %xmm10, 32(%rsp)
+	vmovdqa %xmm11, 48(%rsp)
+	movq %rax, 64(%rsp)
+	vmovdqa %xmm6, 448(%rsp)
+	vmovdqa %xmm6, 464(%rsp)
+	vmovdqa %xmm7, 480(%rsp)
+	vmovdqa %xmm7, 496(%rsp)
+	cmpq $512, %rcx
+	jae .Lchacha_blocks_avx2_atleast512
+	cmp $256, %rcx
+	jae .Lchacha_blocks_avx2_atleast256
+	jmp .Lchacha_blocks_avx2_below256
+	.p2align 6,,63
+.Lchacha_blocks_avx2_atleast512:
+	movq 48(%rsp), %rax
+	leaq 1(%rax), %r8
+	leaq 2(%rax), %r9
+	leaq 3(%rax), %r10
+	leaq 4(%rax), %rbx
+	leaq 5(%rax), %r11
+	leaq 6(%rax), %r12
+	leaq 7(%rax), %r13
+	leaq 8(%rax), %r14
+	movl %eax, 128(%rsp)
+	movl %r8d, 4+128(%rsp)
+	movl %r9d, 8+128(%rsp)
+	movl %r10d, 12+128(%rsp)
+	movl %ebx, 16+128(%rsp)
+	movl %r11d, 20+128(%rsp)
+	movl %r12d, 24+128(%rsp)
+	movl %r13d, 28+128(%rsp)
+	shrq $32, %rax
+	shrq $32, %r8
+	shrq $32, %r9
+	shrq $32, %r10
+	shrq $32, %rbx
+	shrq $32, %r11
+	shrq $32, %r12
+	shrq $32, %r13
+	movl %eax, 160(%rsp)
+	movl %r8d, 4+160(%rsp)
+	movl %r9d, 8+160(%rsp)
+	movl %r10d, 12+160(%rsp)
+	movl %ebx, 16+160(%rsp)
+	movl %r11d, 20+160(%rsp)
+	movl %r12d, 24+160(%rsp)
+	movl %r13d, 28+160(%rsp)
+	movq %r14, 48(%rsp)
+	movq 64(%rsp), %rax
+	vpbroadcastd 0(%rsp), %ymm0
+	vpbroadcastd 4+0(%rsp), %ymm1
+	vpbroadcastd 8+0(%rsp), %ymm2
+	vpbroadcastd 12+0(%rsp), %ymm3
+	vpbroadcastd 16(%rsp), %ymm4
+	vpbroadcastd 4+16(%rsp), %ymm5
+	vpbroadcastd 8+16(%rsp), %ymm6
+	vpbroadcastd 12+16(%rsp), %ymm7
+	vpbroadcastd 32(%rsp), %ymm8
+	vpbroadcastd 4+32(%rsp), %ymm9
+	vpbroadcastd 8+32(%rsp), %ymm10
+	vpbroadcastd 12+32(%rsp), %ymm11
+	vpbroadcastd 8+48(%rsp), %ymm14
+	vpbroadcastd 12+48(%rsp), %ymm15
+	vmovdqa 128(%rsp), %ymm12
+	vmovdqa 160(%rsp), %ymm13
+.Lchacha_blocks_avx2_mainloop1:
+	vpaddd %ymm0, %ymm4, %ymm0
+	vpaddd %ymm1, %ymm5, %ymm1
+	vpxor %ymm12, %ymm0, %ymm12
+	vpxor %ymm13, %ymm1, %ymm13
+	vpaddd %ymm2, %ymm6, %ymm2
+	vpaddd %ymm3, %ymm7, %ymm3
+	vpxor %ymm14, %ymm2, %ymm14
+	vpxor %ymm15, %ymm3, %ymm15
+	vpshufb 448(%rsp), %ymm12, %ymm12
+	vpshufb 448(%rsp), %ymm13, %ymm13
+	vpaddd %ymm8, %ymm12, %ymm8
+	vpaddd %ymm9, %ymm13, %ymm9
+	vpshufb 448(%rsp), %ymm14, %ymm14
+	vpshufb 448(%rsp), %ymm15, %ymm15
+	vpaddd %ymm10, %ymm14, %ymm10
+	vpaddd %ymm11, %ymm15, %ymm11
+	vmovdqa %ymm12, 96(%rsp)
+	vpxor %ymm4, %ymm8, %ymm4
+	vpxor %ymm5, %ymm9, %ymm5
+	vpslld $ 12, %ymm4, %ymm12
+	vpsrld $20, %ymm4, %ymm4
+	vpxor %ymm4, %ymm12, %ymm4
+	vpslld $ 12, %ymm5, %ymm12
+	vpsrld $20, %ymm5, %ymm5
+	vpxor %ymm5, %ymm12, %ymm5
+	vpxor %ymm6, %ymm10, %ymm6
+	vpxor %ymm7, %ymm11, %ymm7
+	vpslld $ 12, %ymm6, %ymm12
+	vpsrld $20, %ymm6, %ymm6
+	vpxor %ymm6, %ymm12, %ymm6
+	vpslld $ 12, %ymm7, %ymm12
+	vpsrld $20, %ymm7, %ymm7
+	vpxor %ymm7, %ymm12, %ymm7
+	vpaddd %ymm0, %ymm4, %ymm0
+	vpaddd %ymm1, %ymm5, %ymm1
+	vpxor 96(%rsp), %ymm0, %ymm12
+	vpxor %ymm13, %ymm1, %ymm13
+	vpaddd %ymm2, %ymm6, %ymm2
+	vpaddd %ymm3, %ymm7, %ymm3
+	vpxor %ymm14, %ymm2, %ymm14
+	vpxor %ymm15, %ymm3, %ymm15
+	vpshufb 480(%rsp), %ymm12, %ymm12
+	vpshufb 480(%rsp), %ymm13, %ymm13
+	vpaddd %ymm8, %ymm12, %ymm8
+	vpaddd %ymm9, %ymm13, %ymm9
+	vpshufb 480(%rsp), %ymm14, %ymm14
+	vpshufb 480(%rsp), %ymm15, %ymm15
+	vpaddd %ymm10, %ymm14, %ymm10
+	vpaddd %ymm11, %ymm15, %ymm11
+	vmovdqa %ymm12, 96(%rsp)
+	vpxor %ymm4, %ymm8, %ymm4
+	vpxor %ymm5, %ymm9, %ymm5
+	vpslld $ 7, %ymm4, %ymm12
+	vpsrld $25, %ymm4, %ymm4
+	vpxor %ymm4, %ymm12, %ymm4
+	vpslld $ 7, %ymm5, %ymm12
+	vpsrld $25, %ymm5, %ymm5
+	vpxor %ymm5, %ymm12, %ymm5
+	vpxor %ymm6, %ymm10, %ymm6
+	vpxor %ymm7, %ymm11, %ymm7
+	vpslld $ 7, %ymm6, %ymm12
+	vpsrld $25, %ymm6, %ymm6
+	vpxor %ymm6, %ymm12, %ymm6
+	vpslld $ 7, %ymm7, %ymm12
+	vpsrld $25, %ymm7, %ymm7
+	vpxor %ymm7, %ymm12, %ymm7
+	vpaddd %ymm0, %ymm5, %ymm0
+	vpaddd %ymm1, %ymm6, %ymm1
+	vpxor %ymm15, %ymm0, %ymm15
+	vpxor 96(%rsp), %ymm1, %ymm12
+	vpaddd %ymm2, %ymm7, %ymm2
+	vpaddd %ymm3, %ymm4, %ymm3
+	vpxor %ymm13, %ymm2, %ymm13
+	vpxor %ymm14, %ymm3, %ymm14
+	vpshufb 448(%rsp), %ymm15, %ymm15
+	vpshufb 448(%rsp), %ymm12, %ymm12
+	vpaddd %ymm10, %ymm15, %ymm10
+	vpaddd %ymm11, %ymm12, %ymm11
+	vpshufb 448(%rsp), %ymm13, %ymm13
+	vpshufb 448(%rsp), %ymm14, %ymm14
+	vpaddd %ymm8, %ymm13, %ymm8
+	vpaddd %ymm9, %ymm14, %ymm9
+	vmovdqa %ymm15, 96(%rsp)
+	vpxor %ymm5, %ymm10, %ymm5
+	vpxor %ymm6, %ymm11, %ymm6
+	vpslld $ 12, %ymm5, %ymm15
+	vpsrld $20, %ymm5, %ymm5
+	vpxor %ymm5, %ymm15, %ymm5
+	vpslld $ 12, %ymm6, %ymm15
+	vpsrld $20, %ymm6, %ymm6
+	vpxor %ymm6, %ymm15, %ymm6
+	vpxor %ymm7, %ymm8, %ymm7
+	vpxor %ymm4, %ymm9, %ymm4
+	vpslld $ 12, %ymm7, %ymm15
+	vpsrld $20, %ymm7, %ymm7
+	vpxor %ymm7, %ymm15, %ymm7
+	vpslld $ 12, %ymm4, %ymm15
+	vpsrld $20, %ymm4, %ymm4
+	vpxor %ymm4, %ymm15, %ymm4
+	vpaddd %ymm0, %ymm5, %ymm0
+	vpaddd %ymm1, %ymm6, %ymm1
+	vpxor 96(%rsp), %ymm0, %ymm15
+	vpxor %ymm12, %ymm1, %ymm12
+	vpaddd %ymm2, %ymm7, %ymm2
+	vpaddd %ymm3, %ymm4, %ymm3
+	vpxor %ymm13, %ymm2, %ymm13
+	vpxor %ymm14, %ymm3, %ymm14
+	vpshufb 480(%rsp), %ymm15, %ymm15
+	vpshufb 480(%rsp), %ymm12, %ymm12
+	vpaddd %ymm10, %ymm15, %ymm10
+	vpaddd %ymm11, %ymm12, %ymm11
+	vpshufb 480(%rsp), %ymm13, %ymm13
+	vpshufb 480(%rsp), %ymm14, %ymm14
+	vpaddd %ymm8, %ymm13, %ymm8
+	vpaddd %ymm9, %ymm14, %ymm9
+	vmovdqa %ymm15, 96(%rsp)
+	vpxor %ymm5, %ymm10, %ymm5
+	vpxor %ymm6, %ymm11, %ymm6
+	vpslld $ 7, %ymm5, %ymm15
+	vpsrld $25, %ymm5, %ymm5
+	vpxor %ymm5, %ymm15, %ymm5
+	vpslld $ 7, %ymm6, %ymm15
+	vpsrld $25, %ymm6, %ymm6
+	vpxor %ymm6, %ymm15, %ymm6
+	vpxor %ymm7, %ymm8, %ymm7
+	vpxor %ymm4, %ymm9, %ymm4
+	vpslld $ 7, %ymm7, %ymm15
+	vpsrld $25, %ymm7, %ymm7
+	vpxor %ymm7, %ymm15, %ymm7
+	vpslld $ 7, %ymm4, %ymm15
+	vpsrld $25, %ymm4, %ymm4
+	vpxor %ymm4, %ymm15, %ymm4
+	vmovdqa 96(%rsp), %ymm15
+	subq $2, %rax
+	jnz .Lchacha_blocks_avx2_mainloop1
+	vmovdqa %ymm8, 192(%rsp)
+	vmovdqa %ymm9, 224(%rsp)
+	vmovdqa %ymm10, 256(%rsp)
+	vmovdqa %ymm11, 288(%rsp)
+	vmovdqa %ymm12, 320(%rsp)
+	vmovdqa %ymm13, 352(%rsp)
+	vmovdqa %ymm14, 384(%rsp)
+	vmovdqa %ymm15, 416(%rsp)
+	vpbroadcastd 0(%rsp), %ymm8
+	vpbroadcastd 4+0(%rsp), %ymm9
+	vpbroadcastd 8+0(%rsp), %ymm10
+	vpbroadcastd 12+0(%rsp), %ymm11
+	vpbroadcastd 16(%rsp), %ymm12
+	vpbroadcastd 4+16(%rsp), %ymm13
+	vpbroadcastd 8+16(%rsp), %ymm14
+	vpbroadcastd 12+16(%rsp), %ymm15
+	vpaddd %ymm8, %ymm0, %ymm0
+	vpaddd %ymm9, %ymm1, %ymm1
+	vpaddd %ymm10, %ymm2, %ymm2
+	vpaddd %ymm11, %ymm3, %ymm3
+	vpaddd %ymm12, %ymm4, %ymm4
+	vpaddd %ymm13, %ymm5, %ymm5
+	vpaddd %ymm14, %ymm6, %ymm6
+	vpaddd %ymm15, %ymm7, %ymm7
+	vpunpckldq %ymm1, %ymm0, %ymm8
+	vpunpckldq %ymm3, %ymm2, %ymm9
+	vpunpckhdq %ymm1, %ymm0, %ymm12
+	vpunpckhdq %ymm3, %ymm2, %ymm13
+	vpunpckldq %ymm5, %ymm4, %ymm10
+	vpunpckldq %ymm7, %ymm6, %ymm11
+	vpunpckhdq %ymm5, %ymm4, %ymm14
+	vpunpckhdq %ymm7, %ymm6, %ymm15
+	vpunpcklqdq %ymm9, %ymm8, %ymm0
+	vpunpcklqdq %ymm11, %ymm10, %ymm1
+	vpunpckhqdq %ymm9, %ymm8, %ymm2
+	vpunpckhqdq %ymm11, %ymm10, %ymm3
+	vpunpcklqdq %ymm13, %ymm12, %ymm4
+	vpunpcklqdq %ymm15, %ymm14, %ymm5
+	vpunpckhqdq %ymm13, %ymm12, %ymm6
+	vpunpckhqdq %ymm15, %ymm14, %ymm7
+	vperm2i128 $0x20, %ymm1, %ymm0, %ymm8
+	vperm2i128 $0x20, %ymm3, %ymm2, %ymm9
+	vperm2i128 $0x31, %ymm1, %ymm0, %ymm12
+	vperm2i128 $0x31, %ymm3, %ymm2, %ymm13
+	vperm2i128 $0x20, %ymm5, %ymm4, %ymm10
+	vperm2i128 $0x20, %ymm7, %ymm6, %ymm11
+	vperm2i128 $0x31, %ymm5, %ymm4, %ymm14
+	vperm2i128 $0x31, %ymm7, %ymm6, %ymm15
+	andq %rsi, %rsi
+	jz .Lchacha_blocks_avx2_noinput1
+	vpxor 0(%rsi), %ymm8, %ymm8
+	vpxor 64(%rsi), %ymm9, %ymm9
+	vpxor 128(%rsi), %ymm10, %ymm10
+	vpxor 192(%rsi), %ymm11, %ymm11
+	vpxor 256(%rsi), %ymm12, %ymm12
+	vpxor 320(%rsi), %ymm13, %ymm13
+	vpxor 384(%rsi), %ymm14, %ymm14
+	vpxor 448(%rsi), %ymm15, %ymm15
+	vmovdqu %ymm8, 0(%rdx)
+	vmovdqu %ymm9, 64(%rdx)
+	vmovdqu %ymm10, 128(%rdx)
+	vmovdqu %ymm11, 192(%rdx)
+	vmovdqu %ymm12, 256(%rdx)
+	vmovdqu %ymm13, 320(%rdx)
+	vmovdqu %ymm14, 384(%rdx)
+	vmovdqu %ymm15, 448(%rdx)
+	vmovdqa 192(%rsp), %ymm0
+	vmovdqa 224(%rsp), %ymm1
+	vmovdqa 256(%rsp), %ymm2
+	vmovdqa 288(%rsp), %ymm3
+	vmovdqa 320(%rsp), %ymm4
+	vmovdqa 352(%rsp), %ymm5
+	vmovdqa 384(%rsp), %ymm6
+	vmovdqa 416(%rsp), %ymm7
+	vpbroadcastd 32(%rsp), %ymm8
+	vpbroadcastd 4+32(%rsp), %ymm9
+	vpbroadcastd 8+32(%rsp), %ymm10
+	vpbroadcastd 12+32(%rsp), %ymm11
+	vmovdqa 128(%rsp), %ymm12
+	vmovdqa 160(%rsp), %ymm13
+	vpbroadcastd 8+48(%rsp), %ymm14
+	vpbroadcastd 12+48(%rsp), %ymm15
+	vpaddd %ymm8, %ymm0, %ymm0
+	vpaddd %ymm9, %ymm1, %ymm1
+	vpaddd %ymm10, %ymm2, %ymm2
+	vpaddd %ymm11, %ymm3, %ymm3
+	vpaddd %ymm12, %ymm4, %ymm4
+	vpaddd %ymm13, %ymm5, %ymm5
+	vpaddd %ymm14, %ymm6, %ymm6
+	vpaddd %ymm15, %ymm7, %ymm7
+	vpunpckldq %ymm1, %ymm0, %ymm8
+	vpunpckldq %ymm3, %ymm2, %ymm9
+	vpunpckhdq %ymm1, %ymm0, %ymm12
+	vpunpckhdq %ymm3, %ymm2, %ymm13
+	vpunpckldq %ymm5, %ymm4, %ymm10
+	vpunpckldq %ymm7, %ymm6, %ymm11
+	vpunpckhdq %ymm5, %ymm4, %ymm14
+	vpunpckhdq %ymm7, %ymm6, %ymm15
+	vpunpcklqdq %ymm9, %ymm8, %ymm0
+	vpunpcklqdq %ymm11, %ymm10, %ymm1
+	vpunpckhqdq %ymm9, %ymm8, %ymm2
+	vpunpckhqdq %ymm11, %ymm10, %ymm3
+	vpunpcklqdq %ymm13, %ymm12, %ymm4
+	vpunpcklqdq %ymm15, %ymm14, %ymm5
+	vpunpckhqdq %ymm13, %ymm12, %ymm6
+	vpunpckhqdq %ymm15, %ymm14, %ymm7
+	vperm2i128 $0x20, %ymm1, %ymm0, %ymm8
+	vperm2i128 $0x20, %ymm3, %ymm2, %ymm9
+	vperm2i128 $0x31, %ymm1, %ymm0, %ymm12
+	vperm2i128 $0x31, %ymm3, %ymm2, %ymm13
+	vperm2i128 $0x20, %ymm5, %ymm4, %ymm10
+	vperm2i128 $0x20, %ymm7, %ymm6, %ymm11
+	vperm2i128 $0x31, %ymm5, %ymm4, %ymm14
+	vperm2i128 $0x31, %ymm7, %ymm6, %ymm15
+	vpxor 32(%rsi), %ymm8, %ymm8
+	vpxor 96(%rsi), %ymm9, %ymm9
+	vpxor 160(%rsi), %ymm10, %ymm10
+	vpxor 224(%rsi), %ymm11, %ymm11
+	vpxor 288(%rsi), %ymm12, %ymm12
+	vpxor 352(%rsi), %ymm13, %ymm13
+	vpxor 416(%rsi), %ymm14, %ymm14
+	vpxor 480(%rsi), %ymm15, %ymm15
+	vmovdqu %ymm8, 32(%rdx)
+	vmovdqu %ymm9, 96(%rdx)
+	vmovdqu %ymm10, 160(%rdx)
+	vmovdqu %ymm11, 224(%rdx)
+	vmovdqu %ymm12, 288(%rdx)
+	vmovdqu %ymm13, 352(%rdx)
+	vmovdqu %ymm14, 416(%rdx)
+	vmovdqu %ymm15, 480(%rdx)
+	addq $512, %rsi
+	jmp .Lchacha_blocks_avx2_mainloop1_cont
+.Lchacha_blocks_avx2_noinput1:
+	vmovdqu %ymm8, 0(%rdx)
+	vmovdqu %ymm9, 64(%rdx)
+	vmovdqu %ymm10, 128(%rdx)
+	vmovdqu %ymm11, 192(%rdx)
+	vmovdqu %ymm12, 256(%rdx)
+	vmovdqu %ymm13, 320(%rdx)
+	vmovdqu %ymm14, 384(%rdx)
+	vmovdqu %ymm15, 448(%rdx)
+	vmovdqa 192(%rsp), %ymm0
+	vmovdqa 224(%rsp), %ymm1
+	vmovdqa 256(%rsp), %ymm2
+	vmovdqa 288(%rsp), %ymm3
+	vmovdqa 320(%rsp), %ymm4
+	vmovdqa 352(%rsp), %ymm5
+	vmovdqa 384(%rsp), %ymm6
+	vmovdqa 416(%rsp), %ymm7
+	vpbroadcastd 32(%rsp), %ymm8
+	vpbroadcastd 4+32(%rsp), %ymm9
+	vpbroadcastd 8+32(%rsp), %ymm10
+	vpbroadcastd 12+32(%rsp), %ymm11
+	vmovdqa 128(%rsp), %ymm12
+	vmovdqa 160(%rsp), %ymm13
+	vpbroadcastd 8+48(%rsp), %ymm14
+	vpbroadcastd 12+48(%rsp), %ymm15
+	vpaddd %ymm8, %ymm0, %ymm0
+	vpaddd %ymm9, %ymm1, %ymm1
+	vpaddd %ymm10, %ymm2, %ymm2
+	vpaddd %ymm11, %ymm3, %ymm3
+	vpaddd %ymm12, %ymm4, %ymm4
+	vpaddd %ymm13, %ymm5, %ymm5
+	vpaddd %ymm14, %ymm6, %ymm6
+	vpaddd %ymm15, %ymm7, %ymm7
+	vpunpckldq %ymm1, %ymm0, %ymm8
+	vpunpckldq %ymm3, %ymm2, %ymm9
+	vpunpckhdq %ymm1, %ymm0, %ymm12
+	vpunpckhdq %ymm3, %ymm2, %ymm13
+	vpunpckldq %ymm5, %ymm4, %ymm10
+	vpunpckldq %ymm7, %ymm6, %ymm11
+	vpunpckhdq %ymm5, %ymm4, %ymm14
+	vpunpckhdq %ymm7, %ymm6, %ymm15
+	vpunpcklqdq %ymm9, %ymm8, %ymm0
+	vpunpcklqdq %ymm11, %ymm10, %ymm1
+	vpunpckhqdq %ymm9, %ymm8, %ymm2
+	vpunpckhqdq %ymm11, %ymm10, %ymm3
+	vpunpcklqdq %ymm13, %ymm12, %ymm4
+	vpunpcklqdq %ymm15, %ymm14, %ymm5
+	vpunpckhqdq %ymm13, %ymm12, %ymm6
+	vpunpckhqdq %ymm15, %ymm14, %ymm7
+	vperm2i128 $0x20, %ymm1, %ymm0, %ymm8
+	vperm2i128 $0x20, %ymm3, %ymm2, %ymm9
+	vperm2i128 $0x31, %ymm1, %ymm0, %ymm12
+	vperm2i128 $0x31, %ymm3, %ymm2, %ymm13
+	vperm2i128 $0x20, %ymm5, %ymm4, %ymm10
+	vperm2i128 $0x20, %ymm7, %ymm6, %ymm11
+	vperm2i128 $0x31, %ymm5, %ymm4, %ymm14
+	vperm2i128 $0x31, %ymm7, %ymm6, %ymm15
+	vmovdqu %ymm8, 32(%rdx)
+	vmovdqu %ymm9, 96(%rdx)
+	vmovdqu %ymm10, 160(%rdx)
+	vmovdqu %ymm11, 224(%rdx)
+	vmovdqu %ymm12, 288(%rdx)
+	vmovdqu %ymm13, 352(%rdx)
+	vmovdqu %ymm14, 416(%rdx)
+	vmovdqu %ymm15, 480(%rdx)
+.Lchacha_blocks_avx2_mainloop1_cont:
+	addq $512, %rdx
+	subq $512, %rcx
+	cmp $512, %rcx
+	jae .Lchacha_blocks_avx2_atleast512
+	cmp $256, %rcx
+	jb .Lchacha_blocks_avx2_below256_fixup
+.Lchacha_blocks_avx2_atleast256:
+	movq 48(%rsp), %rax
+	leaq 1(%rax), %r8
+	leaq 2(%rax), %r9
+	leaq 3(%rax), %r10
+	leaq 4(%rax), %rbx
+	movl %eax, 128(%rsp)
+	movl %r8d, 4+128(%rsp)
+	movl %r9d, 8+128(%rsp)
+	movl %r10d, 12+128(%rsp)
+	shrq $32, %rax
+	shrq $32, %r8
+	shrq $32, %r9
+	shrq $32, %r10
+	movl %eax, 160(%rsp)
+	movl %r8d, 4+160(%rsp)
+	movl %r9d, 8+160(%rsp)
+	movl %r10d, 12+160(%rsp)
+	movq %rbx, 48(%rsp)
+	movq 64(%rsp), %rax
+	vpbroadcastd 0(%rsp), %xmm0
+	vpbroadcastd 4+0(%rsp), %xmm1
+	vpbroadcastd 8+0(%rsp), %xmm2
+	vpbroadcastd 12+0(%rsp), %xmm3
+	vpbroadcastd 16(%rsp), %xmm4
+	vpbroadcastd 4+16(%rsp), %xmm5
+	vpbroadcastd 8+16(%rsp), %xmm6
+	vpbroadcastd 12+16(%rsp), %xmm7
+	vpbroadcastd 32(%rsp), %xmm8
+	vpbroadcastd 4+32(%rsp), %xmm9
+	vpbroadcastd 8+32(%rsp), %xmm10
+	vpbroadcastd 12+32(%rsp), %xmm11
+	vmovdqa 128(%rsp), %xmm12
+	vmovdqa 160(%rsp), %xmm13
+	vpbroadcastd 8+48(%rsp), %xmm14
+	vpbroadcastd 12+48(%rsp), %xmm15
+.Lchacha_blocks_avx2_mainloop2:
+	vpaddd %xmm0, %xmm4, %xmm0
+	vpaddd %xmm1, %xmm5, %xmm1
+	vpxor %xmm12, %xmm0, %xmm12
+	vpxor %xmm13, %xmm1, %xmm13
+	vpaddd %xmm2, %xmm6, %xmm2
+	vpaddd %xmm3, %xmm7, %xmm3
+	vpxor %xmm14, %xmm2, %xmm14
+	vpxor %xmm15, %xmm3, %xmm15
+	vpshufb 448(%rsp), %xmm12, %xmm12
+	vpshufb 448(%rsp), %xmm13, %xmm13
+	vpaddd %xmm8, %xmm12, %xmm8
+	vpaddd %xmm9, %xmm13, %xmm9
+	vpshufb 448(%rsp), %xmm14, %xmm14
+	vpshufb 448(%rsp), %xmm15, %xmm15
+	vpaddd %xmm10, %xmm14, %xmm10
+	vpaddd %xmm11, %xmm15, %xmm11
+	vmovdqa %xmm12, 96(%rsp)
+	vpxor %xmm4, %xmm8, %xmm4
+	vpxor %xmm5, %xmm9, %xmm5
+	vpslld $ 12, %xmm4, %xmm12
+	vpsrld $20, %xmm4, %xmm4
+	vpxor %xmm4, %xmm12, %xmm4
+	vpslld $ 12, %xmm5, %xmm12
+	vpsrld $20, %xmm5, %xmm5
+	vpxor %xmm5, %xmm12, %xmm5
+	vpxor %xmm6, %xmm10, %xmm6
+	vpxor %xmm7, %xmm11, %xmm7
+	vpslld $ 12, %xmm6, %xmm12
+	vpsrld $20, %xmm6, %xmm6
+	vpxor %xmm6, %xmm12, %xmm6
+	vpslld $ 12, %xmm7, %xmm12
+	vpsrld $20, %xmm7, %xmm7
+	vpxor %xmm7, %xmm12, %xmm7
+	vpaddd %xmm0, %xmm4, %xmm0
+	vpaddd %xmm1, %xmm5, %xmm1
+	vpxor 96(%rsp), %xmm0, %xmm12
+	vpxor %xmm13, %xmm1, %xmm13
+	vpaddd %xmm2, %xmm6, %xmm2
+	vpaddd %xmm3, %xmm7, %xmm3
+	vpxor %xmm14, %xmm2, %xmm14
+	vpxor %xmm15, %xmm3, %xmm15
+	vpshufb 480(%rsp), %xmm12, %xmm12
+	vpshufb 480(%rsp), %xmm13, %xmm13
+	vpaddd %xmm8, %xmm12, %xmm8
+	vpaddd %xmm9, %xmm13, %xmm9
+	vpshufb 480(%rsp), %xmm14, %xmm14
+	vpshufb 480(%rsp), %xmm15, %xmm15
+	vpaddd %xmm10, %xmm14, %xmm10
+	vpaddd %xmm11, %xmm15, %xmm11
+	vmovdqa %xmm12, 96(%rsp)
+	vpxor %xmm4, %xmm8, %xmm4
+	vpxor %xmm5, %xmm9, %xmm5
+	vpslld $ 7, %xmm4, %xmm12
+	vpsrld $25, %xmm4, %xmm4
+	vpxor %xmm4, %xmm12, %xmm4
+	vpslld $ 7, %xmm5, %xmm12
+	vpsrld $25, %xmm5, %xmm5
+	vpxor %xmm5, %xmm12, %xmm5
+	vpxor %xmm6, %xmm10, %xmm6
+	vpxor %xmm7, %xmm11, %xmm7
+	vpslld $ 7, %xmm6, %xmm12
+	vpsrld $25, %xmm6, %xmm6
+	vpxor %xmm6, %xmm12, %xmm6
+	vpslld $ 7, %xmm7, %xmm12
+	vpsrld $25, %xmm7, %xmm7
+	vpxor %xmm7, %xmm12, %xmm7
+	vpaddd %xmm0, %xmm5, %xmm0
+	vpaddd %xmm1, %xmm6, %xmm1
+	vpxor %xmm15, %xmm0, %xmm15
+	vpxor 96(%rsp), %xmm1, %xmm12
+	vpaddd %xmm2, %xmm7, %xmm2
+	vpaddd %xmm3, %xmm4, %xmm3
+	vpxor %xmm13, %xmm2, %xmm13
+	vpxor %xmm14, %xmm3, %xmm14
+	vpshufb 448(%rsp), %xmm15, %xmm15
+	vpshufb 448(%rsp), %xmm12, %xmm12
+	vpaddd %xmm10, %xmm15, %xmm10
+	vpaddd %xmm11, %xmm12, %xmm11
+	vpshufb 448(%rsp), %xmm13, %xmm13
+	vpshufb 448(%rsp), %xmm14, %xmm14
+	vpaddd %xmm8, %xmm13, %xmm8
+	vpaddd %xmm9, %xmm14, %xmm9
+	vmovdqa %xmm15, 96(%rsp)
+	vpxor %xmm5, %xmm10, %xmm5
+	vpxor %xmm6, %xmm11, %xmm6
+	vpslld $ 12, %xmm5, %xmm15
+	vpsrld $20, %xmm5, %xmm5
+	vpxor %xmm5, %xmm15, %xmm5
+	vpslld $ 12, %xmm6, %xmm15
+	vpsrld $20, %xmm6, %xmm6
+	vpxor %xmm6, %xmm15, %xmm6
+	vpxor %xmm7, %xmm8, %xmm7
+	vpxor %xmm4, %xmm9, %xmm4
+	vpslld $ 12, %xmm7, %xmm15
+	vpsrld $20, %xmm7, %xmm7
+	vpxor %xmm7, %xmm15, %xmm7
+	vpslld $ 12, %xmm4, %xmm15
+	vpsrld $20, %xmm4, %xmm4
+	vpxor %xmm4, %xmm15, %xmm4
+	vpaddd %xmm0, %xmm5, %xmm0
+	vpaddd %xmm1, %xmm6, %xmm1
+	vpxor 96(%rsp), %xmm0, %xmm15
+	vpxor %xmm12, %xmm1, %xmm12
+	vpaddd %xmm2, %xmm7, %xmm2
+	vpaddd %xmm3, %xmm4, %xmm3
+	vpxor %xmm13, %xmm2, %xmm13
+	vpxor %xmm14, %xmm3, %xmm14
+	vpshufb 480(%rsp), %xmm15, %xmm15
+	vpshufb 480(%rsp), %xmm12, %xmm12
+	vpaddd %xmm10, %xmm15, %xmm10
+	vpaddd %xmm11, %xmm12, %xmm11
+	vpshufb 480(%rsp), %xmm13, %xmm13
+	vpshufb 480(%rsp), %xmm14, %xmm14
+	vpaddd %xmm8, %xmm13, %xmm8
+	vpaddd %xmm9, %xmm14, %xmm9
+	vmovdqa %xmm15, 96(%rsp)
+	vpxor %xmm5, %xmm10, %xmm5
+	vpxor %xmm6, %xmm11, %xmm6
+	vpslld $ 7, %xmm5, %xmm15
+	vpsrld $25, %xmm5, %xmm5
+	vpxor %xmm5, %xmm15, %xmm5
+	vpslld $ 7, %xmm6, %xmm15
+	vpsrld $25, %xmm6, %xmm6
+	vpxor %xmm6, %xmm15, %xmm6
+	vpxor %xmm7, %xmm8, %xmm7
+	vpxor %xmm4, %xmm9, %xmm4
+	vpslld $ 7, %xmm7, %xmm15
+	vpsrld $25, %xmm7, %xmm7
+	vpxor %xmm7, %xmm15, %xmm7
+	vpslld $ 7, %xmm4, %xmm15
+	vpsrld $25, %xmm4, %xmm4
+	vpxor %xmm4, %xmm15, %xmm4
+	vmovdqa 96(%rsp), %xmm15
+	subq $2, %rax
+	jnz .Lchacha_blocks_avx2_mainloop2
+	vmovdqa %xmm8, 192(%rsp)
+	vmovdqa %xmm9, 208(%rsp)
+	vmovdqa %xmm10, 224(%rsp)
+	vmovdqa %xmm11, 240(%rsp)
+	vmovdqa %xmm12, 256(%rsp)
+	vmovdqa %xmm13, 272(%rsp)
+	vmovdqa %xmm14, 288(%rsp)
+	vmovdqa %xmm15, 304(%rsp)
+	vpbroadcastd 0(%rsp), %xmm8
+	vpbroadcastd 4+0(%rsp), %xmm9
+	vpbroadcastd 8+0(%rsp), %xmm10
+	vpbroadcastd 12+0(%rsp), %xmm11
+	vpbroadcastd 16(%rsp), %xmm12
+	vpbroadcastd 4+16(%rsp), %xmm13
+	vpbroadcastd 8+16(%rsp), %xmm14
+	vpbroadcastd 12+16(%rsp), %xmm15
+	vpaddd %xmm8, %xmm0, %xmm0
+	vpaddd %xmm9, %xmm1, %xmm1
+	vpaddd %xmm10, %xmm2, %xmm2
+	vpaddd %xmm11, %xmm3, %xmm3
+	vpaddd %xmm12, %xmm4, %xmm4
+	vpaddd %xmm13, %xmm5, %xmm5
+	vpaddd %xmm14, %xmm6, %xmm6
+	vpaddd %xmm15, %xmm7, %xmm7
+	vpunpckldq %xmm1, %xmm0, %xmm8
+	vpunpckldq %xmm3, %xmm2, %xmm9
+	vpunpckhdq %xmm1, %xmm0, %xmm12
+	vpunpckhdq %xmm3, %xmm2, %xmm13
+	vpunpckldq %xmm5, %xmm4, %xmm10
+	vpunpckldq %xmm7, %xmm6, %xmm11
+	vpunpckhdq %xmm5, %xmm4, %xmm14
+	vpunpckhdq %xmm7, %xmm6, %xmm15
+	vpunpcklqdq %xmm9, %xmm8, %xmm0
+	vpunpcklqdq %xmm11, %xmm10, %xmm1
+	vpunpckhqdq %xmm9, %xmm8, %xmm2
+	vpunpckhqdq %xmm11, %xmm10, %xmm3
+	vpunpcklqdq %xmm13, %xmm12, %xmm4
+	vpunpcklqdq %xmm15, %xmm14, %xmm5
+	vpunpckhqdq %xmm13, %xmm12, %xmm6
+	vpunpckhqdq %xmm15, %xmm14, %xmm7
+	andq %rsi, %rsi
+	jz .Lchacha_blocks_avx2_noinput2
+	vpxor 0(%rsi), %xmm0, %xmm0
+	vpxor 16(%rsi), %xmm1, %xmm1
+	vpxor 64(%rsi), %xmm2, %xmm2
+	vpxor 80(%rsi), %xmm3, %xmm3
+	vpxor 128(%rsi), %xmm4, %xmm4
+	vpxor 144(%rsi), %xmm5, %xmm5
+	vpxor 192(%rsi), %xmm6, %xmm6
+	vpxor 208(%rsi), %xmm7, %xmm7
+	vmovdqu %xmm0, 0(%rdx)
+	vmovdqu %xmm1, 16(%rdx)
+	vmovdqu %xmm2, 64(%rdx)
+	vmovdqu %xmm3, 80(%rdx)
+	vmovdqu %xmm4, 128(%rdx)
+	vmovdqu %xmm5, 144(%rdx)
+	vmovdqu %xmm6, 192(%rdx)
+	vmovdqu %xmm7, 208(%rdx)
+	vmovdqa 192(%rsp), %xmm0
+	vmovdqa 208(%rsp), %xmm1
+	vmovdqa 224(%rsp), %xmm2
+	vmovdqa 240(%rsp), %xmm3
+	vmovdqa 256(%rsp), %xmm4
+	vmovdqa 272(%rsp), %xmm5
+	vmovdqa 288(%rsp), %xmm6
+	vmovdqa 304(%rsp), %xmm7
+	vpbroadcastd 32(%rsp), %xmm8
+	vpbroadcastd 4+32(%rsp), %xmm9
+	vpbroadcastd 8+32(%rsp), %xmm10
+	vpbroadcastd 12+32(%rsp), %xmm11
+	vmovdqa 128(%rsp), %xmm12
+	vmovdqa 160(%rsp), %xmm13
+	vpbroadcastd 8+48(%rsp), %xmm14
+	vpbroadcastd 12+48(%rsp), %xmm15
+	vpaddd %xmm8, %xmm0, %xmm0
+	vpaddd %xmm9, %xmm1, %xmm1
+	vpaddd %xmm10, %xmm2, %xmm2
+	vpaddd %xmm11, %xmm3, %xmm3
+	vpaddd %xmm12, %xmm4, %xmm4
+	vpaddd %xmm13, %xmm5, %xmm5
+	vpaddd %xmm14, %xmm6, %xmm6
+	vpaddd %xmm15, %xmm7, %xmm7
+	vpunpckldq %xmm1, %xmm0, %xmm8
+	vpunpckldq %xmm3, %xmm2, %xmm9
+	vpunpckhdq %xmm1, %xmm0, %xmm12
+	vpunpckhdq %xmm3, %xmm2, %xmm13
+	vpunpckldq %xmm5, %xmm4, %xmm10
+	vpunpckldq %xmm7, %xmm6, %xmm11
+	vpunpckhdq %xmm5, %xmm4, %xmm14
+	vpunpckhdq %xmm7, %xmm6, %xmm15
+	vpunpcklqdq %xmm9, %xmm8, %xmm0
+	vpunpcklqdq %xmm11, %xmm10, %xmm1
+	vpunpckhqdq %xmm9, %xmm8, %xmm2
+	vpunpckhqdq %xmm11, %xmm10, %xmm3
+	vpunpcklqdq %xmm13, %xmm12, %xmm4
+	vpunpcklqdq %xmm15, %xmm14, %xmm5
+	vpunpckhqdq %xmm13, %xmm12, %xmm6
+	vpunpckhqdq %xmm15, %xmm14, %xmm7
+	vpxor 32(%rsi), %xmm0, %xmm0
+	vpxor 48(%rsi), %xmm1, %xmm1
+	vpxor 96(%rsi), %xmm2, %xmm2
+	vpxor 112(%rsi), %xmm3, %xmm3
+	vpxor 160(%rsi), %xmm4, %xmm4
+	vpxor 176(%rsi), %xmm5, %xmm5
+	vpxor 224(%rsi), %xmm6, %xmm6
+	vpxor 240(%rsi), %xmm7, %xmm7
+	vmovdqu %xmm0, 32(%rdx)
+	vmovdqu %xmm1, 48(%rdx)
+	vmovdqu %xmm2, 96(%rdx)
+	vmovdqu %xmm3, 112(%rdx)
+	vmovdqu %xmm4, 160(%rdx)
+	vmovdqu %xmm5, 176(%rdx)
+	vmovdqu %xmm6, 224(%rdx)
+	vmovdqu %xmm7, 240(%rdx)
+	addq $256, %rsi
+	jmp .Lchacha_blocks_avx2_mainloop2_cont
+.Lchacha_blocks_avx2_noinput2:
+	vmovdqu %xmm0, 0(%rdx)
+	vmovdqu %xmm1, 16(%rdx)
+	vmovdqu %xmm2, 64(%rdx)
+	vmovdqu %xmm3, 80(%rdx)
+	vmovdqu %xmm4, 128(%rdx)
+	vmovdqu %xmm5, 144(%rdx)
+	vmovdqu %xmm6, 192(%rdx)
+	vmovdqu %xmm7, 208(%rdx)
+	vmovdqa 192(%rsp), %xmm0
+	vmovdqa 208(%rsp), %xmm1
+	vmovdqa 224(%rsp), %xmm2
+	vmovdqa 240(%rsp), %xmm3
+	vmovdqa 256(%rsp), %xmm4
+	vmovdqa 272(%rsp), %xmm5
+	vmovdqa 288(%rsp), %xmm6
+	vmovdqa 304(%rsp), %xmm7
+	vpbroadcastd 32(%rsp), %xmm8
+	vpbroadcastd 4+32(%rsp), %xmm9
+	vpbroadcastd 8+32(%rsp), %xmm10
+	vpbroadcastd 12+32(%rsp), %xmm11
+	vmovdqa 128(%rsp), %xmm12
+	vmovdqa 160(%rsp), %xmm13
+	vpbroadcastd 8+48(%rsp), %xmm14
+	vpbroadcastd 12+48(%rsp), %xmm15
+	vpaddd %xmm8, %xmm0, %xmm0
+	vpaddd %xmm9, %xmm1, %xmm1
+	vpaddd %xmm10, %xmm2, %xmm2
+	vpaddd %xmm11, %xmm3, %xmm3
+	vpaddd %xmm12, %xmm4, %xmm4
+	vpaddd %xmm13, %xmm5, %xmm5
+	vpaddd %xmm14, %xmm6, %xmm6
+	vpaddd %xmm15, %xmm7, %xmm7
+	vpunpckldq %xmm1, %xmm0, %xmm8
+	vpunpckldq %xmm3, %xmm2, %xmm9
+	vpunpckhdq %xmm1, %xmm0, %xmm12
+	vpunpckhdq %xmm3, %xmm2, %xmm13
+	vpunpckldq %xmm5, %xmm4, %xmm10
+	vpunpckldq %xmm7, %xmm6, %xmm11
+	vpunpckhdq %xmm5, %xmm4, %xmm14
+	vpunpckhdq %xmm7, %xmm6, %xmm15
+	vpunpcklqdq %xmm9, %xmm8, %xmm0
+	vpunpcklqdq %xmm11, %xmm10, %xmm1
+	vpunpckhqdq %xmm9, %xmm8, %xmm2
+	vpunpckhqdq %xmm11, %xmm10, %xmm3
+	vpunpcklqdq %xmm13, %xmm12, %xmm4
+	vpunpcklqdq %xmm15, %xmm14, %xmm5
+	vpunpckhqdq %xmm13, %xmm12, %xmm6
+	vpunpckhqdq %xmm15, %xmm14, %xmm7
+	vmovdqu %xmm0, 32(%rdx)
+	vmovdqu %xmm1, 48(%rdx)
+	vmovdqu %xmm2, 96(%rdx)
+	vmovdqu %xmm3, 112(%rdx)
+	vmovdqu %xmm4, 160(%rdx)
+	vmovdqu %xmm5, 176(%rdx)
+	vmovdqu %xmm6, 224(%rdx)
+	vmovdqu %xmm7, 240(%rdx)
+.Lchacha_blocks_avx2_mainloop2_cont:
+	addq $256, %rdx
+	subq $256, %rcx
+	cmp $256, %rcx
+	jae .Lchacha_blocks_avx2_atleast256
+.Lchacha_blocks_avx2_below256_fixup:
+	vmovdqa 448(%rsp), %xmm6
+	vmovdqa 480(%rsp), %xmm7
+	vmovdqa 0(%rsp), %xmm8
+	vmovdqa 16(%rsp), %xmm9
+	vmovdqa 32(%rsp), %xmm10
+	vmovdqa 48(%rsp), %xmm11
+	movq $1, %r9
+.Lchacha_blocks_avx2_below256:
+	vmovq %r9, %xmm5
+	andq %rcx, %rcx
+	jz .Lchacha_blocks_avx2_done
+	cmpq $64, %rcx
+	jae .Lchacha_blocks_avx2_above63
+	movq %rdx, %r9
+	andq %rsi, %rsi
+	jz .Lchacha_blocks_avx2_noinput3
+	movq %rcx, %r10
+	movq %rsp, %rdx
+	addq %r10, %rsi
+	addq %r10, %rdx
+	negq %r10
+.Lchacha_blocks_avx2_copyinput:
+	movb (%rsi, %r10), %al
+	movb %al, (%rdx, %r10)
+	incq %r10
+	jnz .Lchacha_blocks_avx2_copyinput
+	movq %rsp, %rsi
+.Lchacha_blocks_avx2_noinput3:
+	movq %rsp, %rdx
+.Lchacha_blocks_avx2_above63:
+	vmovdqa %xmm8, %xmm0
+	vmovdqa %xmm9, %xmm1
+	vmovdqa %xmm10, %xmm2
+	vmovdqa %xmm11, %xmm3
+	movq 64(%rsp), %rax
+.Lchacha_blocks_avx2_mainloop3:
+	vpaddd %xmm0, %xmm1, %xmm0
+	vpxor %xmm3, %xmm0, %xmm3
+	vpshufb %xmm6, %xmm3, %xmm3
+	vpaddd %xmm2, %xmm3, %xmm2
+	vpxor %xmm1, %xmm2, %xmm1
+	vpslld $12, %xmm1, %xmm4
+	vpsrld $20, %xmm1, %xmm1
+	vpxor %xmm1, %xmm4, %xmm1
+	vpaddd %xmm0, %xmm1, %xmm0
+	vpxor %xmm3, %xmm0, %xmm3
+	vpshufb %xmm7, %xmm3, %xmm3
+	vpshufd $0x93, %xmm0, %xmm0
+	vpaddd %xmm2, %xmm3, %xmm2
+	vpshufd $0x4e, %xmm3, %xmm3
+	vpxor %xmm1, %xmm2, %xmm1
+	vpshufd $0x39, %xmm2, %xmm2
+	vpslld $7, %xmm1, %xmm4
+	vpsrld $25, %xmm1, %xmm1
+	vpxor %xmm1, %xmm4, %xmm1
+	vpaddd %xmm0, %xmm1, %xmm0
+	vpxor %xmm3, %xmm0, %xmm3
+	vpshufb %xmm6, %xmm3, %xmm3
+	vpaddd %xmm2, %xmm3, %xmm2
+	vpxor %xmm1, %xmm2, %xmm1
+	vpslld $12, %xmm1, %xmm4
+	vpsrld $20, %xmm1, %xmm1
+	vpxor %xmm1, %xmm4, %xmm1
+	vpaddd %xmm0, %xmm1, %xmm0
+	vpxor %xmm3, %xmm0, %xmm3
+	vpshufb %xmm7, %xmm3, %xmm3
+	vpshufd $0x39, %xmm0, %xmm0
+	vpaddd %xmm2, %xmm3, %xmm2
+	vpshufd $0x4e, %xmm3, %xmm3
+	vpxor %xmm1, %xmm2, %xmm1
+	vpshufd $0x93, %xmm2, %xmm2
+	vpslld $7, %xmm1, %xmm4
+	vpsrld $25, %xmm1, %xmm1
+	vpxor %xmm1, %xmm4, %xmm1
+	subq $2, %rax
+	jnz .Lchacha_blocks_avx2_mainloop3
+	vpaddd %xmm0, %xmm8, %xmm0
+	vpaddd %xmm1, %xmm9, %xmm1
+	vpaddd %xmm2, %xmm10, %xmm2
+	vpaddd %xmm3, %xmm11, %xmm3
+	andq %rsi, %rsi
+	jz .Lchacha_blocks_avx2_noinput4
+	vpxor 0(%rsi), %xmm0, %xmm0
+	vpxor 16(%rsi), %xmm1, %xmm1
+	vpxor 32(%rsi), %xmm2, %xmm2
+	vpxor 48(%rsi), %xmm3, %xmm3
+	addq $64, %rsi
+.Lchacha_blocks_avx2_noinput4:
+	vmovdqu %xmm0, 0(%rdx)
+	vmovdqu %xmm1, 16(%rdx)
+	vmovdqu %xmm2, 32(%rdx)
+	vmovdqu %xmm3, 48(%rdx)
+	vpaddq %xmm11, %xmm5, %xmm11
+	cmpq $64, %rcx
+	jbe .Lchacha_blocks_avx2_mainloop3_finishup
+	addq $64, %rdx
+	subq $64, %rcx
+	jmp .Lchacha_blocks_avx2_below256
+.Lchacha_blocks_avx2_mainloop3_finishup:
+	cmpq $64, %rcx
+	je .Lchacha_blocks_avx2_done
+	addq %rcx, %r9
+	addq %rcx, %rdx
+	negq %rcx
+.Lchacha_blocks_avx2_copyoutput:
+	movb (%rdx, %rcx), %al
+	movb %al, (%r9, %rcx)
+	incq %rcx
+	jnz .Lchacha_blocks_avx2_copyoutput
+.Lchacha_blocks_avx2_done:
+	vmovdqu %xmm11, 48(%rdi)
+	movq %rbp, %rsp
+	popq %r14
+	popq %r13
+	popq %r12
+	popq %rbp
+	popq %rbx
+	vzeroall
+	movl $(63 + 512), %eax
+	ret
+.size _gcry_chacha20_amd64_avx2_blocks,.-_gcry_chacha20_amd64_avx2_blocks;
+
+.data
+.align 16
+.LC:
+.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 */
+
+#endif /*defined(USE_CHACHA20)*/
+#endif /*__x86_64*/
+
diff --git a/cipher/chacha20.c b/cipher/chacha20.c
index 1ffa458..7d85719 100644
--- a/cipher/chacha20.c
+++ b/cipher/chacha20.c
@@ -47,6 +47,13 @@
 # define USE_SSSE3 1
 #endif
 
+/* USE_AVX2 indicates whether to compile with Intel AVX2 code. */
+#undef USE_AVX2
+#if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && \
+    defined(HAVE_GCC_INLINE_ASM_AVX2)
+# define USE_AVX2 1
+#endif
+
 
 #define CHACHA20_MIN_KEY_SIZE 16	/* Bytes.  */
 #define CHACHA20_MAX_KEY_SIZE 32	/* Bytes.  */
@@ -70,6 +77,9 @@ typedef struct CHACHA20_context_s
 #ifdef USE_SSSE3
   unsigned int use_ssse3:1;
 #endif
+#ifdef USE_AVX2
+  unsigned int use_avx2:1;
+#endif
   chacha20_core_t core;
 } CHACHA20_context_t;
 
@@ -89,6 +99,21 @@ chacha20_core_ssse3 (u32 * dst, CHACHA20_context_t * ctx)
 
 #endif /* USE_SSSE3 */
 
+#ifdef USE_AVX2
+
+unsigned int _gcry_chacha20_amd64_avx2_blocks(u32 *state,
+					      const byte *in,
+					      byte *out,
+					      size_t bytes);
+
+static unsigned int
+chacha20_core_avx2 (u32 * dst, CHACHA20_context_t * ctx)
+{
+  return _gcry_chacha20_amd64_avx2_blocks(ctx->input, NULL, (byte *)dst, 64);
+}
+
+#endif /* USE_AVX2 */
+
 
 static void chacha20_setiv (void *context, const byte * iv, size_t ivlen);
 static const char *selftest (void);
@@ -312,6 +337,12 @@ chacha20_do_setkey (CHACHA20_context_t * ctx,
     ctx->core = chacha20_core_ssse3;
 #endif
 
+#ifdef USE_AVX2
+  ctx->use_avx2 = (features & HWF_INTEL_AVX2) != 0;
+  if (ctx->use_avx2)
+    ctx->core = chacha20_core_avx2;
+#endif
+
   (void)features;
 
   chacha20_keysetup (ctx, key, keylen);
@@ -387,6 +418,11 @@ chacha20_do_encrypt_stream (CHACHA20_context_t * ctx,
 
       if (0)
         { }
+#ifdef USE_AVX2
+      else if (ctx->use_avx2)
+        burn = _gcry_chacha20_amd64_avx2_blocks(ctx->input, inbuf, outbuf,
+                                                bytes);
+#endif
 #ifdef USE_SSSE3
       else if (ctx->use_ssse3)
         burn = _gcry_chacha20_amd64_ssse3_blocks(ctx->input, inbuf, outbuf,
@@ -440,7 +476,7 @@ selftest (void)
 {
   CHACHA20_context_t ctx;
   byte scratch[127 + 1];
-  byte buf[256 + 64 + 4];
+  byte buf[512 + 64 + 4];
   int i;
 
   /* From draft-strombergson-chacha-test-vectors */
diff --git a/configure.ac b/configure.ac
index 7d0dc88..1da37dd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1815,6 +1815,7 @@ if test "$found" = "1" ; then
       x86_64-*-*)
          # Build with the assembly implementation
          GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-ssse3-amd64.lo"
+         GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-avx2-amd64.lo"
       ;;
    esac
 fi




More information about the Gcrypt-devel mailing list