pkgconfig: Fix libgcrypt.pc.
[libgcrypt.git] / cipher / chacha20-amd64-avx2.S
1 /* chacha20-amd64-avx2.S  -  AVX2 implementation of ChaCha20 cipher
2  *
3  * Copyright (C) 2017-2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /*
22  * Based on D. J. Bernstein reference implementation at
23  * http://cr.yp.to/chacha.html:
24  *
25  * chacha-regs.c version 20080118
26  * D. J. Bernstein
27  * Public domain.
28  */
29
30 #ifdef __x86_64
31 #include <config.h>
32 #if defined(HAVE_GCC_INLINE_ASM_AVX2) && \
33    (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
34     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
35
36 .text
37
38 #include "asm-common-amd64.h"
39 #include "asm-poly1305-amd64.h"
40
41 /* register macros */
42 #define INPUT %rdi
43 #define DST   %rsi
44 #define SRC   %rdx
45 #define NBLKS %rcx
46 #define ROUND %eax
47
48 /* stack structure */
49 #define STACK_VEC_X12 (32)
50 #define STACK_VEC_X13 (32 + STACK_VEC_X12)
51 #define STACK_TMP     (32 + STACK_VEC_X13)
52 #define STACK_TMP1    (32 + STACK_TMP)
53
54 #define STACK_MAX     (32 + STACK_TMP1)
55
56 /* vector registers */
57 #define X0 %ymm0
58 #define X1 %ymm1
59 #define X2 %ymm2
60 #define X3 %ymm3
61 #define X4 %ymm4
62 #define X5 %ymm5
63 #define X6 %ymm6
64 #define X7 %ymm7
65 #define X8 %ymm8
66 #define X9 %ymm9
67 #define X10 %ymm10
68 #define X11 %ymm11
69 #define X12 %ymm12
70 #define X13 %ymm13
71 #define X14 %ymm14
72 #define X15 %ymm15
73
74 #define X0h %xmm0
75 #define X1h %xmm1
76 #define X2h %xmm2
77 #define X3h %xmm3
78 #define X4h %xmm4
79 #define X5h %xmm5
80 #define X6h %xmm6
81 #define X7h %xmm7
82 #define X8h %xmm8
83 #define X9h %xmm9
84 #define X10h %xmm10
85 #define X11h %xmm11
86 #define X12h %xmm12
87 #define X13h %xmm13
88 #define X14h %xmm14
89 #define X15h %xmm15
90
91 /**********************************************************************
92   helper macros
93  **********************************************************************/
94
95 /* 4x4 32-bit integer matrix transpose */
96 #define transpose_4x4(x0,x1,x2,x3,t1,t2) \
97         vpunpckhdq x1, x0, t2; \
98         vpunpckldq x1, x0, x0; \
99         \
100         vpunpckldq x3, x2, t1; \
101         vpunpckhdq x3, x2, x2; \
102         \
103         vpunpckhqdq t1, x0, x1; \
104         vpunpcklqdq t1, x0, x0; \
105         \
106         vpunpckhqdq x2, t2, x3; \
107         vpunpcklqdq x2, t2, x2;
108
109 /* 2x2 128-bit matrix transpose */
110 #define transpose_16byte_2x2(x0,x1,t1) \
111         vmovdqa    x0, t1; \
112         vperm2i128 $0x20, x1, x0, x0; \
113         vperm2i128 $0x31, x1, t1, x1;
114
115 /* xor register with unaligned src and save to unaligned dst */
116 #define xor_src_dst(dst, src, offset, xreg) \
117         vpxor offset(src), xreg, xreg; \
118         vmovdqu xreg, offset(dst);
119
120 /**********************************************************************
121   8-way chacha20
122  **********************************************************************/
123
124 #define ROTATE2(v1,v2,c,tmp)    \
125         vpsrld $(32 - (c)), v1, tmp;    \
126         vpslld $(c), v1, v1;            \
127         vpaddb tmp, v1, v1;             \
128         vpsrld $(32 - (c)), v2, tmp;    \
129         vpslld $(c), v2, v2;            \
130         vpaddb tmp, v2, v2;
131
132 #define ROTATE_SHUF_2(v1,v2,shuf)       \
133         vpshufb shuf, v1, v1;           \
134         vpshufb shuf, v2, v2;
135
136 #define XOR(ds,s) \
137         vpxor s, ds, ds;
138
139 #define PLUS(ds,s) \
140         vpaddd s, ds, ds;
141
142 #define QUARTERROUND2(a1,b1,c1,d1,a2,b2,c2,d2,ign,tmp1,\
143                       interleave_op1,interleave_op2,\
144                       interleave_op3,interleave_op4)            \
145         vbroadcasti128 .Lshuf_rol16 rRIP, tmp1;                 \
146                 interleave_op1;                                 \
147         PLUS(a1,b1); PLUS(a2,b2); XOR(d1,a1); XOR(d2,a2);       \
148             ROTATE_SHUF_2(d1, d2, tmp1);                        \
149                 interleave_op2;                                 \
150         PLUS(c1,d1); PLUS(c2,d2); XOR(b1,c1); XOR(b2,c2);       \
151             ROTATE2(b1, b2, 12, tmp1);                          \
152         vbroadcasti128 .Lshuf_rol8 rRIP, tmp1;                  \
153                 interleave_op3;                                 \
154         PLUS(a1,b1); PLUS(a2,b2); XOR(d1,a1); XOR(d2,a2);       \
155             ROTATE_SHUF_2(d1, d2, tmp1);                        \
156                 interleave_op4;                                 \
157         PLUS(c1,d1); PLUS(c2,d2); XOR(b1,c1); XOR(b2,c2);       \
158             ROTATE2(b1, b2,  7, tmp1);
159
160 .align 32
161 chacha20_data:
162 .Lshuf_rol16:
163         .byte 2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13
164 .Lshuf_rol8:
165         .byte 3,0,1,2,7,4,5,6,11,8,9,10,15,12,13,14
166 .Linc_counter:
167         .byte 0,1,2,3,4,5,6,7
168 .Lunsigned_cmp:
169         .long 0x80000000
170
171 .align 8
172 .globl _gcry_chacha20_amd64_avx2_blocks8
173 ELF(.type _gcry_chacha20_amd64_avx2_blocks8,@function;)
174
175 _gcry_chacha20_amd64_avx2_blocks8:
176         /* input:
177          *      %rdi: input
178          *      %rsi: dst
179          *      %rdx: src
180          *      %rcx: nblks (multiple of 8)
181          */
182         CFI_STARTPROC();
183
184         vzeroupper;
185
186         pushq %rbp;
187         CFI_PUSH(%rbp);
188         movq %rsp, %rbp;
189         CFI_DEF_CFA_REGISTER(%rbp);
190
191         subq $STACK_MAX, %rsp;
192         andq $~31, %rsp;
193
194 .Loop8:
195         mov $20, ROUND;
196
197         /* Construct counter vectors X12 and X13 */
198         vpmovzxbd .Linc_counter rRIP, X0;
199         vpbroadcastd .Lunsigned_cmp rRIP, X2;
200         vpbroadcastd (12 * 4)(INPUT), X12;
201         vpbroadcastd (13 * 4)(INPUT), X13;
202         vpaddd X0, X12, X12;
203         vpxor X2, X0, X0;
204         vpxor X2, X12, X1;
205         vpcmpgtd X1, X0, X0;
206         vpsubd X0, X13, X13;
207         vmovdqa X12, (STACK_VEC_X12)(%rsp);
208         vmovdqa X13, (STACK_VEC_X13)(%rsp);
209
210         /* Load vectors */
211         vpbroadcastd (0 * 4)(INPUT), X0;
212         vpbroadcastd (1 * 4)(INPUT), X1;
213         vpbroadcastd (2 * 4)(INPUT), X2;
214         vpbroadcastd (3 * 4)(INPUT), X3;
215         vpbroadcastd (4 * 4)(INPUT), X4;
216         vpbroadcastd (5 * 4)(INPUT), X5;
217         vpbroadcastd (6 * 4)(INPUT), X6;
218         vpbroadcastd (7 * 4)(INPUT), X7;
219         vpbroadcastd (8 * 4)(INPUT), X8;
220         vpbroadcastd (9 * 4)(INPUT), X9;
221         vpbroadcastd (10 * 4)(INPUT), X10;
222         vpbroadcastd (11 * 4)(INPUT), X11;
223         vpbroadcastd (14 * 4)(INPUT), X14;
224         vpbroadcastd (15 * 4)(INPUT), X15;
225         vmovdqa X15, (STACK_TMP)(%rsp);
226
227 .Lround2:
228         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,,,,)
229         vmovdqa (STACK_TMP)(%rsp), X15;
230         vmovdqa X8, (STACK_TMP)(%rsp);
231         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,,,,)
232         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,,,,)
233         vmovdqa (STACK_TMP)(%rsp), X8;
234         vmovdqa X15, (STACK_TMP)(%rsp);
235         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,,,,)
236         sub $2, ROUND;
237         jnz .Lround2;
238
239         vmovdqa X8, (STACK_TMP1)(%rsp);
240
241         /* tmp := X15 */
242         vpbroadcastd (0 * 4)(INPUT), X15;
243         PLUS(X0, X15);
244         vpbroadcastd (1 * 4)(INPUT), X15;
245         PLUS(X1, X15);
246         vpbroadcastd (2 * 4)(INPUT), X15;
247         PLUS(X2, X15);
248         vpbroadcastd (3 * 4)(INPUT), X15;
249         PLUS(X3, X15);
250         vpbroadcastd (4 * 4)(INPUT), X15;
251         PLUS(X4, X15);
252         vpbroadcastd (5 * 4)(INPUT), X15;
253         PLUS(X5, X15);
254         vpbroadcastd (6 * 4)(INPUT), X15;
255         PLUS(X6, X15);
256         vpbroadcastd (7 * 4)(INPUT), X15;
257         PLUS(X7, X15);
258         transpose_4x4(X0, X1, X2, X3, X8, X15);
259         transpose_4x4(X4, X5, X6, X7, X8, X15);
260         vmovdqa (STACK_TMP1)(%rsp), X8;
261         transpose_16byte_2x2(X0, X4, X15);
262         transpose_16byte_2x2(X1, X5, X15);
263         transpose_16byte_2x2(X2, X6, X15);
264         transpose_16byte_2x2(X3, X7, X15);
265         vmovdqa (STACK_TMP)(%rsp), X15;
266         xor_src_dst(DST, SRC, (64 * 0 + 16 * 0), X0);
267         xor_src_dst(DST, SRC, (64 * 1 + 16 * 0), X1);
268         vpbroadcastd (8 * 4)(INPUT), X0;
269         PLUS(X8, X0);
270         vpbroadcastd (9 * 4)(INPUT), X0;
271         PLUS(X9, X0);
272         vpbroadcastd (10 * 4)(INPUT), X0;
273         PLUS(X10, X0);
274         vpbroadcastd (11 * 4)(INPUT), X0;
275         PLUS(X11, X0);
276         vmovdqa (STACK_VEC_X12)(%rsp), X0;
277         PLUS(X12, X0);
278         vmovdqa (STACK_VEC_X13)(%rsp), X0;
279         PLUS(X13, X0);
280         vpbroadcastd (14 * 4)(INPUT), X0;
281         PLUS(X14, X0);
282         vpbroadcastd (15 * 4)(INPUT), X0;
283         PLUS(X15, X0);
284         xor_src_dst(DST, SRC, (64 * 2 + 16 * 0), X2);
285         xor_src_dst(DST, SRC, (64 * 3 + 16 * 0), X3);
286
287         /* Update counter */
288         addq $8, (12 * 4)(INPUT);
289
290         transpose_4x4(X8, X9, X10, X11, X0, X1);
291         transpose_4x4(X12, X13, X14, X15, X0, X1);
292         xor_src_dst(DST, SRC, (64 * 4 + 16 * 0), X4);
293         xor_src_dst(DST, SRC, (64 * 5 + 16 * 0), X5);
294         transpose_16byte_2x2(X8, X12, X0);
295         transpose_16byte_2x2(X9, X13, X0);
296         transpose_16byte_2x2(X10, X14, X0);
297         transpose_16byte_2x2(X11, X15, X0);
298         xor_src_dst(DST, SRC, (64 * 6 + 16 * 0), X6);
299         xor_src_dst(DST, SRC, (64 * 7 + 16 * 0), X7);
300         xor_src_dst(DST, SRC, (64 * 0 + 16 * 2), X8);
301         xor_src_dst(DST, SRC, (64 * 1 + 16 * 2), X9);
302         xor_src_dst(DST, SRC, (64 * 2 + 16 * 2), X10);
303         xor_src_dst(DST, SRC, (64 * 3 + 16 * 2), X11);
304         xor_src_dst(DST, SRC, (64 * 4 + 16 * 2), X12);
305         xor_src_dst(DST, SRC, (64 * 5 + 16 * 2), X13);
306         xor_src_dst(DST, SRC, (64 * 6 + 16 * 2), X14);
307         xor_src_dst(DST, SRC, (64 * 7 + 16 * 2), X15);
308
309         sub $8, NBLKS;
310         lea (8 * 64)(DST), DST;
311         lea (8 * 64)(SRC), SRC;
312         jnz .Loop8;
313
314         /* clear the used vector registers and stack */
315         vpxor X0, X0, X0;
316         vmovdqa X0, (STACK_VEC_X12)(%rsp);
317         vmovdqa X0, (STACK_VEC_X13)(%rsp);
318         vmovdqa X0, (STACK_TMP)(%rsp);
319         vmovdqa X0, (STACK_TMP1)(%rsp);
320         vzeroall;
321
322         /* eax zeroed by round loop. */
323         leave;
324         CFI_LEAVE();
325         ret;
326         CFI_ENDPROC();
327 ELF(.size _gcry_chacha20_amd64_avx2_blocks8,
328           .-_gcry_chacha20_amd64_avx2_blocks8;)
329
330 /**********************************************************************
331   8-way stitched chacha20-poly1305
332  **********************************************************************/
333
334 .align 8
335 .globl _gcry_chacha20_poly1305_amd64_avx2_blocks8
336 ELF(.type _gcry_chacha20_poly1305_amd64_avx2_blocks8,@function;)
337
338 _gcry_chacha20_poly1305_amd64_avx2_blocks8:
339         /* input:
340          *      %rdi: input
341          *      %rsi: dst
342          *      %rdx: src
343          *      %rcx: nblks (multiple of 8)
344          *      %r9: poly1305-state
345          *      %r8: poly1305-src
346          */
347         CFI_STARTPROC();
348
349         pushq %rbp;
350         CFI_PUSH(%rbp);
351         movq %rsp, %rbp;
352         CFI_DEF_CFA_REGISTER(%rbp);
353
354         vzeroupper;
355
356         subq $(8 * 8) + STACK_MAX + 32, %rsp;
357         andq $~31, %rsp;
358
359         movq %rbx, (STACK_MAX + 0 * 8)(%rsp);
360         movq %r12, (STACK_MAX + 1 * 8)(%rsp);
361         movq %r13, (STACK_MAX + 2 * 8)(%rsp);
362         movq %r14, (STACK_MAX + 3 * 8)(%rsp);
363         movq %r15, (STACK_MAX + 4 * 8)(%rsp);
364         CFI_REG_ON_STACK(rbx, STACK_MAX + 0 * 8);
365         CFI_REG_ON_STACK(r12, STACK_MAX + 1 * 8);
366         CFI_REG_ON_STACK(r13, STACK_MAX + 2 * 8);
367         CFI_REG_ON_STACK(r14, STACK_MAX + 3 * 8);
368         CFI_REG_ON_STACK(r15, STACK_MAX + 4 * 8);
369
370         movq %rdx, (STACK_MAX + 5 * 8)(%rsp); # SRC
371         movq %rsi, (STACK_MAX + 6 * 8)(%rsp); # DST
372         movq %rcx, (STACK_MAX + 7 * 8)(%rsp); # NBLKS
373
374         /* Load state */
375         POLY1305_LOAD_STATE();
376
377 .Loop_poly8:
378
379         /* Construct counter vectors X12 and X13 */
380         vpmovzxbd .Linc_counter rRIP, X0;
381         vpbroadcastd .Lunsigned_cmp rRIP, X2;
382         vpbroadcastd (12 * 4)(INPUT), X12;
383         vpbroadcastd (13 * 4)(INPUT), X13;
384         vpaddd X0, X12, X12;
385         vpxor X2, X0, X0;
386         vpxor X2, X12, X1;
387         vpcmpgtd X1, X0, X0;
388         vpsubd X0, X13, X13;
389         vmovdqa X12, (STACK_VEC_X12)(%rsp);
390         vmovdqa X13, (STACK_VEC_X13)(%rsp);
391
392         /* Load vectors */
393         vpbroadcastd (0 * 4)(INPUT), X0;
394         vpbroadcastd (1 * 4)(INPUT), X1;
395         vpbroadcastd (2 * 4)(INPUT), X2;
396         vpbroadcastd (3 * 4)(INPUT), X3;
397         vpbroadcastd (4 * 4)(INPUT), X4;
398         vpbroadcastd (5 * 4)(INPUT), X5;
399         vpbroadcastd (6 * 4)(INPUT), X6;
400         vpbroadcastd (7 * 4)(INPUT), X7;
401         vpbroadcastd (8 * 4)(INPUT), X8;
402         vpbroadcastd (9 * 4)(INPUT), X9;
403         vpbroadcastd (10 * 4)(INPUT), X10;
404         vpbroadcastd (11 * 4)(INPUT), X11;
405         vpbroadcastd (14 * 4)(INPUT), X14;
406         vpbroadcastd (15 * 4)(INPUT), X15;
407         vmovdqa X15, (STACK_TMP)(%rsp);
408
409         # rounds 0,1
410         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
411                       POLY1305_BLOCK_PART1(0 * 16),
412                       POLY1305_BLOCK_PART2(),
413                       POLY1305_BLOCK_PART3(),
414                       POLY1305_BLOCK_PART4())
415         vmovdqa (STACK_TMP)(%rsp), X15;
416         vmovdqa X8, (STACK_TMP)(%rsp);
417         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
418                       POLY1305_BLOCK_PART5(),
419                       POLY1305_BLOCK_PART1(1 * 16),
420                       POLY1305_BLOCK_PART2(),
421                       POLY1305_BLOCK_PART3())
422         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
423                       POLY1305_BLOCK_PART4(),
424                       POLY1305_BLOCK_PART5(),
425                       POLY1305_BLOCK_PART1(2 * 16),
426                       POLY1305_BLOCK_PART2())
427         vmovdqa (STACK_TMP)(%rsp), X8;
428         vmovdqa X15, (STACK_TMP)(%rsp);
429         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
430                       POLY1305_BLOCK_PART3(),
431                       POLY1305_BLOCK_PART4(),
432                       POLY1305_BLOCK_PART5(),
433                       POLY1305_BLOCK_PART1(3 * 16))
434
435         # rounds 2,3
436         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
437                       POLY1305_BLOCK_PART2(),
438                       POLY1305_BLOCK_PART3(),
439                       POLY1305_BLOCK_PART4(),
440                       POLY1305_BLOCK_PART5())
441         vmovdqa (STACK_TMP)(%rsp), X15;
442         vmovdqa X8, (STACK_TMP)(%rsp);
443         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
444                       POLY1305_BLOCK_PART1(4 * 16),
445                       POLY1305_BLOCK_PART2(),
446                       POLY1305_BLOCK_PART3(),
447                       POLY1305_BLOCK_PART4())
448         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
449                       POLY1305_BLOCK_PART5(),
450                       POLY1305_BLOCK_PART1(5 * 16),
451                       POLY1305_BLOCK_PART2(),
452                       POLY1305_BLOCK_PART3())
453         vmovdqa (STACK_TMP)(%rsp), X8;
454         vmovdqa X15, (STACK_TMP)(%rsp);
455         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
456                       POLY1305_BLOCK_PART4(),
457                       POLY1305_BLOCK_PART5(),
458                       POLY1305_BLOCK_PART1(6 * 16),
459                       POLY1305_BLOCK_PART2())
460
461         # rounds 4,5
462         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
463                       POLY1305_BLOCK_PART3(),
464                       POLY1305_BLOCK_PART4(),
465                       POLY1305_BLOCK_PART5(),
466                       POLY1305_BLOCK_PART1(7 * 16))
467         vmovdqa (STACK_TMP)(%rsp), X15;
468         vmovdqa X8, (STACK_TMP)(%rsp);
469         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
470                       POLY1305_BLOCK_PART2(),
471                       POLY1305_BLOCK_PART3(),
472                       POLY1305_BLOCK_PART4(),
473                       POLY1305_BLOCK_PART5())
474         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
475                       POLY1305_BLOCK_PART1(8 * 16),
476                       POLY1305_BLOCK_PART2(),
477                       POLY1305_BLOCK_PART3(),
478                       POLY1305_BLOCK_PART4())
479         vmovdqa (STACK_TMP)(%rsp), X8;
480         vmovdqa X15, (STACK_TMP)(%rsp);
481         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
482                       POLY1305_BLOCK_PART5(),
483                       POLY1305_BLOCK_PART1(9 * 16),
484                       POLY1305_BLOCK_PART2(),
485                       POLY1305_BLOCK_PART3())
486
487         # rounds 6,7
488         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
489                       POLY1305_BLOCK_PART4(),
490                       POLY1305_BLOCK_PART5(),
491                       POLY1305_BLOCK_PART1(10 * 16),
492                       POLY1305_BLOCK_PART2())
493         vmovdqa (STACK_TMP)(%rsp), X15;
494         vmovdqa X8, (STACK_TMP)(%rsp);
495         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
496                       POLY1305_BLOCK_PART3(),
497                       POLY1305_BLOCK_PART4(),
498                       POLY1305_BLOCK_PART5(),
499                       POLY1305_BLOCK_PART1(11 * 16))
500         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
501                       POLY1305_BLOCK_PART2(),
502                       POLY1305_BLOCK_PART3(),
503                       POLY1305_BLOCK_PART4(),
504                       POLY1305_BLOCK_PART5())
505         vmovdqa (STACK_TMP)(%rsp), X8;
506         vmovdqa X15, (STACK_TMP)(%rsp);
507         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
508                       POLY1305_BLOCK_PART1(12 * 16),
509                       POLY1305_BLOCK_PART2(),
510                       POLY1305_BLOCK_PART3(),
511                       POLY1305_BLOCK_PART4())
512
513         # rounds 8,9
514         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
515                       POLY1305_BLOCK_PART5(),
516                       POLY1305_BLOCK_PART1(13 * 16),
517                       POLY1305_BLOCK_PART2(),
518                       POLY1305_BLOCK_PART3())
519         vmovdqa (STACK_TMP)(%rsp), X15;
520         vmovdqa X8, (STACK_TMP)(%rsp);
521         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
522                       POLY1305_BLOCK_PART4(),
523                       POLY1305_BLOCK_PART5(),
524                       POLY1305_BLOCK_PART1(14 * 16),
525                       POLY1305_BLOCK_PART2())
526         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
527                       POLY1305_BLOCK_PART3(),
528                       POLY1305_BLOCK_PART4(),
529                       POLY1305_BLOCK_PART5(),
530                       POLY1305_BLOCK_PART1(15 * 16))
531         vmovdqa (STACK_TMP)(%rsp), X8;
532         vmovdqa X15, (STACK_TMP)(%rsp);
533         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
534                       POLY1305_BLOCK_PART2(),
535                       POLY1305_BLOCK_PART3(),
536                       POLY1305_BLOCK_PART4(),
537                       POLY1305_BLOCK_PART5())
538
539         # rounds 10,11
540         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
541                       POLY1305_BLOCK_PART1(16 * 16),
542                       POLY1305_BLOCK_PART2(),
543                       POLY1305_BLOCK_PART3(),
544                       POLY1305_BLOCK_PART4())
545         vmovdqa (STACK_TMP)(%rsp), X15;
546         vmovdqa X8, (STACK_TMP)(%rsp);
547         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
548                       POLY1305_BLOCK_PART5(),
549                       POLY1305_BLOCK_PART1(17 * 16),
550                       POLY1305_BLOCK_PART2(),
551                       POLY1305_BLOCK_PART3())
552         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
553                       POLY1305_BLOCK_PART4(),
554                       POLY1305_BLOCK_PART5(),
555                       POLY1305_BLOCK_PART1(18 * 16),
556                       POLY1305_BLOCK_PART2())
557         vmovdqa (STACK_TMP)(%rsp), X8;
558         vmovdqa X15, (STACK_TMP)(%rsp);
559         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
560                       POLY1305_BLOCK_PART3(),
561                       POLY1305_BLOCK_PART4(),
562                       POLY1305_BLOCK_PART5(),
563                       POLY1305_BLOCK_PART1(19 * 16))
564
565         # rounds 12,13
566         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
567                       POLY1305_BLOCK_PART2(),
568                       POLY1305_BLOCK_PART3(),
569                       POLY1305_BLOCK_PART4(),
570                       POLY1305_BLOCK_PART5())
571         vmovdqa (STACK_TMP)(%rsp), X15;
572         vmovdqa X8, (STACK_TMP)(%rsp);
573         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
574                       POLY1305_BLOCK_PART1(20 * 16),
575                       POLY1305_BLOCK_PART2(),
576                       POLY1305_BLOCK_PART3(),
577                       POLY1305_BLOCK_PART4())
578         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
579                       POLY1305_BLOCK_PART5(),
580                       POLY1305_BLOCK_PART1(21 * 16),
581                       POLY1305_BLOCK_PART2(),
582                       POLY1305_BLOCK_PART3())
583         vmovdqa (STACK_TMP)(%rsp), X8;
584         vmovdqa X15, (STACK_TMP)(%rsp);
585         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
586                       POLY1305_BLOCK_PART4(),
587                       POLY1305_BLOCK_PART5(),
588                       POLY1305_BLOCK_PART1(22 * 16),
589                       POLY1305_BLOCK_PART2())
590
591         # rounds 14,15
592         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
593                       POLY1305_BLOCK_PART3(),
594                       POLY1305_BLOCK_PART4(),
595                       POLY1305_BLOCK_PART5(),
596                       POLY1305_BLOCK_PART1(23 * 16))
597         vmovdqa (STACK_TMP)(%rsp), X15;
598         vmovdqa X8, (STACK_TMP)(%rsp);
599         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
600                       POLY1305_BLOCK_PART2(),
601                       POLY1305_BLOCK_PART3(),
602                       POLY1305_BLOCK_PART4(),
603                       POLY1305_BLOCK_PART5())
604         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
605                       POLY1305_BLOCK_PART1(24 * 16),
606                       POLY1305_BLOCK_PART2(),
607                       POLY1305_BLOCK_PART3(),
608                       POLY1305_BLOCK_PART4())
609         vmovdqa (STACK_TMP)(%rsp), X8;
610         vmovdqa X15, (STACK_TMP)(%rsp);
611         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
612                       POLY1305_BLOCK_PART5(),
613                       POLY1305_BLOCK_PART1(25 * 16),
614                       POLY1305_BLOCK_PART2(),
615                       POLY1305_BLOCK_PART3())
616
617         # rounds 16,17
618         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
619                       POLY1305_BLOCK_PART4(),
620                       POLY1305_BLOCK_PART5(),
621                       POLY1305_BLOCK_PART1(26 * 16),
622                       POLY1305_BLOCK_PART2())
623         vmovdqa (STACK_TMP)(%rsp), X15;
624         vmovdqa X8, (STACK_TMP)(%rsp);
625         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
626                       POLY1305_BLOCK_PART3(),
627                       POLY1305_BLOCK_PART4(),
628                       POLY1305_BLOCK_PART5(),
629                       POLY1305_BLOCK_PART1(27 * 16))
630         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
631                       POLY1305_BLOCK_PART2(),
632                       POLY1305_BLOCK_PART3(),
633                       POLY1305_BLOCK_PART4(),
634                       POLY1305_BLOCK_PART5())
635         vmovdqa (STACK_TMP)(%rsp), X8;
636         vmovdqa X15, (STACK_TMP)(%rsp);
637         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
638                       POLY1305_BLOCK_PART1(28 * 16),
639                       POLY1305_BLOCK_PART2(),
640                       POLY1305_BLOCK_PART3(),
641                       POLY1305_BLOCK_PART4())
642
643         # rounds 18,19
644         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
645                       POLY1305_BLOCK_PART5(),
646                       POLY1305_BLOCK_PART1(29 * 16),
647                       POLY1305_BLOCK_PART2(),
648                       POLY1305_BLOCK_PART3())
649         vmovdqa (STACK_TMP)(%rsp), X15;
650         vmovdqa X8, (STACK_TMP)(%rsp);
651         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
652                       POLY1305_BLOCK_PART4(),
653                       POLY1305_BLOCK_PART5(),
654                       POLY1305_BLOCK_PART1(30 * 16),
655                       POLY1305_BLOCK_PART2())
656         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
657                       POLY1305_BLOCK_PART3(),
658                       POLY1305_BLOCK_PART4(),
659                       POLY1305_BLOCK_PART5(),
660                       POLY1305_BLOCK_PART1(31 * 16))
661         vmovdqa (STACK_TMP)(%rsp), X8;
662         vmovdqa X15, (STACK_TMP)(%rsp);
663         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
664                       POLY1305_BLOCK_PART2(),
665                       POLY1305_BLOCK_PART3(),
666                       POLY1305_BLOCK_PART4(),
667                       POLY1305_BLOCK_PART5())
668
669         movq (STACK_MAX + 5 * 8)(%rsp), SRC;
670         movq (STACK_MAX + 6 * 8)(%rsp), DST;
671
672         vmovdqa X8, (STACK_TMP1)(%rsp);
673
674         /* tmp := X15 */
675         vpbroadcastd (0 * 4)(INPUT), X15;
676         PLUS(X0, X15);
677         vpbroadcastd (1 * 4)(INPUT), X15;
678         PLUS(X1, X15);
679         vpbroadcastd (2 * 4)(INPUT), X15;
680         PLUS(X2, X15);
681         vpbroadcastd (3 * 4)(INPUT), X15;
682         PLUS(X3, X15);
683         vpbroadcastd (4 * 4)(INPUT), X15;
684         PLUS(X4, X15);
685         vpbroadcastd (5 * 4)(INPUT), X15;
686         PLUS(X5, X15);
687         vpbroadcastd (6 * 4)(INPUT), X15;
688         PLUS(X6, X15);
689         vpbroadcastd (7 * 4)(INPUT), X15;
690         PLUS(X7, X15);
691         transpose_4x4(X0, X1, X2, X3, X8, X15);
692         transpose_4x4(X4, X5, X6, X7, X8, X15);
693         vmovdqa (STACK_TMP1)(%rsp), X8;
694         transpose_16byte_2x2(X0, X4, X15);
695         transpose_16byte_2x2(X1, X5, X15);
696         transpose_16byte_2x2(X2, X6, X15);
697         transpose_16byte_2x2(X3, X7, X15);
698         vmovdqa (STACK_TMP)(%rsp), X15;
699         xor_src_dst(DST, SRC, (64 * 0 + 16 * 0), X0);
700         xor_src_dst(DST, SRC, (64 * 1 + 16 * 0), X1);
701         vpbroadcastd (8 * 4)(INPUT), X0;
702         PLUS(X8, X0);
703         vpbroadcastd (9 * 4)(INPUT), X0;
704         PLUS(X9, X0);
705         vpbroadcastd (10 * 4)(INPUT), X0;
706         PLUS(X10, X0);
707         vpbroadcastd (11 * 4)(INPUT), X0;
708         PLUS(X11, X0);
709         vmovdqa (STACK_VEC_X12)(%rsp), X0;
710         PLUS(X12, X0);
711         vmovdqa (STACK_VEC_X13)(%rsp), X0;
712         PLUS(X13, X0);
713         vpbroadcastd (14 * 4)(INPUT), X0;
714         PLUS(X14, X0);
715         vpbroadcastd (15 * 4)(INPUT), X0;
716         PLUS(X15, X0);
717         xor_src_dst(DST, SRC, (64 * 2 + 16 * 0), X2);
718         xor_src_dst(DST, SRC, (64 * 3 + 16 * 0), X3);
719
720         /* Update counter */
721         addq $8, (12 * 4)(INPUT);
722
723         transpose_4x4(X8, X9, X10, X11, X0, X1);
724         transpose_4x4(X12, X13, X14, X15, X0, X1);
725         xor_src_dst(DST, SRC, (64 * 4 + 16 * 0), X4);
726         xor_src_dst(DST, SRC, (64 * 5 + 16 * 0), X5);
727         transpose_16byte_2x2(X8, X12, X0);
728         transpose_16byte_2x2(X9, X13, X0);
729         transpose_16byte_2x2(X10, X14, X0);
730         transpose_16byte_2x2(X11, X15, X0);
731         xor_src_dst(DST, SRC, (64 * 6 + 16 * 0), X6);
732         xor_src_dst(DST, SRC, (64 * 7 + 16 * 0), X7);
733         xor_src_dst(DST, SRC, (64 * 0 + 16 * 2), X8);
734         xor_src_dst(DST, SRC, (64 * 1 + 16 * 2), X9);
735         xor_src_dst(DST, SRC, (64 * 2 + 16 * 2), X10);
736         xor_src_dst(DST, SRC, (64 * 3 + 16 * 2), X11);
737         xor_src_dst(DST, SRC, (64 * 4 + 16 * 2), X12);
738         xor_src_dst(DST, SRC, (64 * 5 + 16 * 2), X13);
739         xor_src_dst(DST, SRC, (64 * 6 + 16 * 2), X14);
740         xor_src_dst(DST, SRC, (64 * 7 + 16 * 2), X15);
741
742         subq $8, (STACK_MAX + 7 * 8)(%rsp); # NBLKS
743
744         lea (32 * 16)(POLY_RSRC), POLY_RSRC;
745         lea (8 * 64)(DST), DST;
746         lea (8 * 64)(SRC), SRC;
747         movq SRC, (STACK_MAX + 5 * 8)(%rsp);
748         movq DST, (STACK_MAX + 6 * 8)(%rsp);
749
750         jnz .Loop_poly8;
751
752         /* Store state */
753         POLY1305_STORE_STATE();
754
755         /* clear the used vector registers and stack */
756         vpxor X0, X0, X0;
757         vmovdqa X0, (STACK_VEC_X12)(%rsp);
758         vmovdqa X0, (STACK_VEC_X13)(%rsp);
759         vmovdqa X0, (STACK_TMP)(%rsp);
760         vmovdqa X0, (STACK_TMP1)(%rsp);
761         vzeroall;
762
763         movq (STACK_MAX + 0 * 8)(%rsp), %rbx;
764         movq (STACK_MAX + 1 * 8)(%rsp), %r12;
765         movq (STACK_MAX + 2 * 8)(%rsp), %r13;
766         movq (STACK_MAX + 3 * 8)(%rsp), %r14;
767         movq (STACK_MAX + 4 * 8)(%rsp), %r15;
768         CFI_RESTORE(%rbx);
769         CFI_RESTORE(%r12);
770         CFI_RESTORE(%r13);
771         CFI_RESTORE(%r14);
772         CFI_RESTORE(%r15);
773
774         xorl %eax, %eax;
775         leave;
776         CFI_LEAVE();
777         ret;
778         CFI_ENDPROC();
779 ELF(.size _gcry_chacha20_poly1305_amd64_avx2_blocks8,
780           .-_gcry_chacha20_poly1305_amd64_avx2_blocks8;)
781
782 #endif /*defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS)*/
783 #endif /*__x86_64*/