/* chacha20-avx2-amd64.S  -  AMD64/AVX2 implementation of ChaCha20
 *
 * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@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_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
    defined(ENABLE_AVX2_SUPPORT) && USE_CHACHA20

#ifdef __PIC__
#  define RIP (%rip)
#else
#  define RIP
#endif

#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
# define ELF(...) __VA_ARGS__
#else
# define ELF(...) /*_*/
#endif

.text

.align 8
.globl _gcry_chacha20_amd64_avx2_blocks
ELF(.type  _gcry_chacha20_amd64_avx2_blocks,@function;)
_gcry_chacha20_amd64_avx2_blocks:
.Lchacha_blocks_avx2_local:
	vzeroupper
	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
ELF(.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*/
