chacha20-amd64-avx2: optimize output xoring
[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
183         vzeroupper;
184
185         pushq %rbp;
186         movq %rsp, %rbp;
187
188         subq $STACK_MAX, %rsp;
189         andq $~31, %rsp;
190
191 .Loop8:
192         mov $20, ROUND;
193
194         /* Construct counter vectors X12 and X13 */
195         vpmovzxbd .Linc_counter rRIP, X0;
196         vpbroadcastd .Lunsigned_cmp rRIP, X2;
197         vpbroadcastd (12 * 4)(INPUT), X12;
198         vpbroadcastd (13 * 4)(INPUT), X13;
199         vpaddd X0, X12, X12;
200         vpxor X2, X0, X0;
201         vpxor X2, X12, X1;
202         vpcmpgtd X1, X0, X0;
203         vpsubd X0, X13, X13;
204         vmovdqa X12, (STACK_VEC_X12)(%rsp);
205         vmovdqa X13, (STACK_VEC_X13)(%rsp);
206
207         /* Load vectors */
208         vpbroadcastd (0 * 4)(INPUT), X0;
209         vpbroadcastd (1 * 4)(INPUT), X1;
210         vpbroadcastd (2 * 4)(INPUT), X2;
211         vpbroadcastd (3 * 4)(INPUT), X3;
212         vpbroadcastd (4 * 4)(INPUT), X4;
213         vpbroadcastd (5 * 4)(INPUT), X5;
214         vpbroadcastd (6 * 4)(INPUT), X6;
215         vpbroadcastd (7 * 4)(INPUT), X7;
216         vpbroadcastd (8 * 4)(INPUT), X8;
217         vpbroadcastd (9 * 4)(INPUT), X9;
218         vpbroadcastd (10 * 4)(INPUT), X10;
219         vpbroadcastd (11 * 4)(INPUT), X11;
220         vpbroadcastd (14 * 4)(INPUT), X14;
221         vpbroadcastd (15 * 4)(INPUT), X15;
222         vmovdqa X15, (STACK_TMP)(%rsp);
223
224 .Lround2:
225         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,,,,)
226         vmovdqa (STACK_TMP)(%rsp), X15;
227         vmovdqa X8, (STACK_TMP)(%rsp);
228         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,,,,)
229         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,,,,)
230         vmovdqa (STACK_TMP)(%rsp), X8;
231         vmovdqa X15, (STACK_TMP)(%rsp);
232         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,,,,)
233         sub $2, ROUND;
234         jnz .Lround2;
235
236         vmovdqa X8, (STACK_TMP1)(%rsp);
237
238         /* tmp := X15 */
239         vpbroadcastd (0 * 4)(INPUT), X15;
240         PLUS(X0, X15);
241         vpbroadcastd (1 * 4)(INPUT), X15;
242         PLUS(X1, X15);
243         vpbroadcastd (2 * 4)(INPUT), X15;
244         PLUS(X2, X15);
245         vpbroadcastd (3 * 4)(INPUT), X15;
246         PLUS(X3, X15);
247         vpbroadcastd (4 * 4)(INPUT), X15;
248         PLUS(X4, X15);
249         vpbroadcastd (5 * 4)(INPUT), X15;
250         PLUS(X5, X15);
251         vpbroadcastd (6 * 4)(INPUT), X15;
252         PLUS(X6, X15);
253         vpbroadcastd (7 * 4)(INPUT), X15;
254         PLUS(X7, X15);
255         transpose_4x4(X0, X1, X2, X3, X8, X15);
256         transpose_4x4(X4, X5, X6, X7, X8, X15);
257         vmovdqa (STACK_TMP1)(%rsp), X8;
258         transpose_16byte_2x2(X0, X4, X15);
259         transpose_16byte_2x2(X1, X5, X15);
260         transpose_16byte_2x2(X2, X6, X15);
261         transpose_16byte_2x2(X3, X7, X15);
262         vmovdqa (STACK_TMP)(%rsp), X15;
263         xor_src_dst(DST, SRC, (64 * 0 + 16 * 0), X0);
264         xor_src_dst(DST, SRC, (64 * 1 + 16 * 0), X1);
265         vpbroadcastd (8 * 4)(INPUT), X0;
266         PLUS(X8, X0);
267         vpbroadcastd (9 * 4)(INPUT), X0;
268         PLUS(X9, X0);
269         vpbroadcastd (10 * 4)(INPUT), X0;
270         PLUS(X10, X0);
271         vpbroadcastd (11 * 4)(INPUT), X0;
272         PLUS(X11, X0);
273         vmovdqa (STACK_VEC_X12)(%rsp), X0;
274         PLUS(X12, X0);
275         vmovdqa (STACK_VEC_X13)(%rsp), X0;
276         PLUS(X13, X0);
277         vpbroadcastd (14 * 4)(INPUT), X0;
278         PLUS(X14, X0);
279         vpbroadcastd (15 * 4)(INPUT), X0;
280         PLUS(X15, X0);
281         xor_src_dst(DST, SRC, (64 * 2 + 16 * 0), X2);
282         xor_src_dst(DST, SRC, (64 * 3 + 16 * 0), X3);
283
284         /* Update counter */
285         addq $8, (12 * 4)(INPUT);
286
287         transpose_4x4(X8, X9, X10, X11, X0, X1);
288         transpose_4x4(X12, X13, X14, X15, X0, X1);
289         xor_src_dst(DST, SRC, (64 * 4 + 16 * 0), X4);
290         xor_src_dst(DST, SRC, (64 * 5 + 16 * 0), X5);
291         transpose_16byte_2x2(X8, X12, X0);
292         transpose_16byte_2x2(X9, X13, X0);
293         transpose_16byte_2x2(X10, X14, X0);
294         transpose_16byte_2x2(X11, X15, X0);
295         xor_src_dst(DST, SRC, (64 * 6 + 16 * 0), X6);
296         xor_src_dst(DST, SRC, (64 * 7 + 16 * 0), X7);
297         xor_src_dst(DST, SRC, (64 * 0 + 16 * 2), X8);
298         xor_src_dst(DST, SRC, (64 * 1 + 16 * 2), X9);
299         xor_src_dst(DST, SRC, (64 * 2 + 16 * 2), X10);
300         xor_src_dst(DST, SRC, (64 * 3 + 16 * 2), X11);
301         xor_src_dst(DST, SRC, (64 * 4 + 16 * 2), X12);
302         xor_src_dst(DST, SRC, (64 * 5 + 16 * 2), X13);
303         xor_src_dst(DST, SRC, (64 * 6 + 16 * 2), X14);
304         xor_src_dst(DST, SRC, (64 * 7 + 16 * 2), X15);
305
306         sub $8, NBLKS;
307         lea (8 * 64)(DST), DST;
308         lea (8 * 64)(SRC), SRC;
309         jnz .Loop8;
310
311         /* clear the used vector registers and stack */
312         vpxor X0, X0, X0;
313         vmovdqa X0, (STACK_VEC_X12)(%rsp);
314         vmovdqa X0, (STACK_VEC_X13)(%rsp);
315         vmovdqa X0, (STACK_TMP)(%rsp);
316         vmovdqa X0, (STACK_TMP1)(%rsp);
317         vzeroall;
318
319         /* eax zeroed by round loop. */
320         leave;
321         ret;
322 ELF(.size _gcry_chacha20_amd64_avx2_blocks8,
323           .-_gcry_chacha20_amd64_avx2_blocks8;)
324
325 /**********************************************************************
326   8-way stitched chacha20-poly1305
327  **********************************************************************/
328
329 .align 8
330 .globl _gcry_chacha20_poly1305_amd64_avx2_blocks8
331 ELF(.type _gcry_chacha20_poly1305_amd64_avx2_blocks8,@function;)
332
333 _gcry_chacha20_poly1305_amd64_avx2_blocks8:
334         /* input:
335          *      %rdi: input
336          *      %rsi: dst
337          *      %rdx: src
338          *      %rcx: nblks (multiple of 8)
339          *      %r9: poly1305-state
340          *      %r8: poly1305-src
341          */
342
343         pushq %rbp;
344         movq %rsp, %rbp;
345
346         vzeroupper;
347
348         subq $(8 * 8) + STACK_MAX + 32, %rsp;
349         andq $~31, %rsp;
350
351         movq %rbx, (STACK_MAX + 0 * 8)(%rsp);
352         movq %r12, (STACK_MAX + 1 * 8)(%rsp);
353         movq %r13, (STACK_MAX + 2 * 8)(%rsp);
354         movq %r14, (STACK_MAX + 3 * 8)(%rsp);
355         movq %r15, (STACK_MAX + 4 * 8)(%rsp);
356
357         movq %rdx, (STACK_MAX + 5 * 8)(%rsp); # SRC
358         movq %rsi, (STACK_MAX + 6 * 8)(%rsp); # DST
359         movq %rcx, (STACK_MAX + 7 * 8)(%rsp); # NBLKS
360
361         /* Load state */
362         POLY1305_LOAD_STATE();
363
364 .Loop_poly8:
365
366         /* Construct counter vectors X12 and X13 */
367         vpmovzxbd .Linc_counter rRIP, X0;
368         vpbroadcastd .Lunsigned_cmp rRIP, X2;
369         vpbroadcastd (12 * 4)(INPUT), X12;
370         vpbroadcastd (13 * 4)(INPUT), X13;
371         vpaddd X0, X12, X12;
372         vpxor X2, X0, X0;
373         vpxor X2, X12, X1;
374         vpcmpgtd X1, X0, X0;
375         vpsubd X0, X13, X13;
376         vmovdqa X12, (STACK_VEC_X12)(%rsp);
377         vmovdqa X13, (STACK_VEC_X13)(%rsp);
378
379         /* Load vectors */
380         vpbroadcastd (0 * 4)(INPUT), X0;
381         vpbroadcastd (1 * 4)(INPUT), X1;
382         vpbroadcastd (2 * 4)(INPUT), X2;
383         vpbroadcastd (3 * 4)(INPUT), X3;
384         vpbroadcastd (4 * 4)(INPUT), X4;
385         vpbroadcastd (5 * 4)(INPUT), X5;
386         vpbroadcastd (6 * 4)(INPUT), X6;
387         vpbroadcastd (7 * 4)(INPUT), X7;
388         vpbroadcastd (8 * 4)(INPUT), X8;
389         vpbroadcastd (9 * 4)(INPUT), X9;
390         vpbroadcastd (10 * 4)(INPUT), X10;
391         vpbroadcastd (11 * 4)(INPUT), X11;
392         vpbroadcastd (14 * 4)(INPUT), X14;
393         vpbroadcastd (15 * 4)(INPUT), X15;
394         vmovdqa X15, (STACK_TMP)(%rsp);
395
396         # rounds 0,1
397         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
398                       POLY1305_BLOCK_PART1(0 * 16),
399                       POLY1305_BLOCK_PART2(),
400                       POLY1305_BLOCK_PART3(),
401                       POLY1305_BLOCK_PART4())
402         vmovdqa (STACK_TMP)(%rsp), X15;
403         vmovdqa X8, (STACK_TMP)(%rsp);
404         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
405                       POLY1305_BLOCK_PART5(),
406                       POLY1305_BLOCK_PART1(1 * 16),
407                       POLY1305_BLOCK_PART2(),
408                       POLY1305_BLOCK_PART3())
409         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
410                       POLY1305_BLOCK_PART4(),
411                       POLY1305_BLOCK_PART5(),
412                       POLY1305_BLOCK_PART1(2 * 16),
413                       POLY1305_BLOCK_PART2())
414         vmovdqa (STACK_TMP)(%rsp), X8;
415         vmovdqa X15, (STACK_TMP)(%rsp);
416         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
417                       POLY1305_BLOCK_PART3(),
418                       POLY1305_BLOCK_PART4(),
419                       POLY1305_BLOCK_PART5(),
420                       POLY1305_BLOCK_PART1(3 * 16))
421
422         # rounds 2,3
423         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
424                       POLY1305_BLOCK_PART2(),
425                       POLY1305_BLOCK_PART3(),
426                       POLY1305_BLOCK_PART4(),
427                       POLY1305_BLOCK_PART5())
428         vmovdqa (STACK_TMP)(%rsp), X15;
429         vmovdqa X8, (STACK_TMP)(%rsp);
430         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
431                       POLY1305_BLOCK_PART1(4 * 16),
432                       POLY1305_BLOCK_PART2(),
433                       POLY1305_BLOCK_PART3(),
434                       POLY1305_BLOCK_PART4())
435         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
436                       POLY1305_BLOCK_PART5(),
437                       POLY1305_BLOCK_PART1(5 * 16),
438                       POLY1305_BLOCK_PART2(),
439                       POLY1305_BLOCK_PART3())
440         vmovdqa (STACK_TMP)(%rsp), X8;
441         vmovdqa X15, (STACK_TMP)(%rsp);
442         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
443                       POLY1305_BLOCK_PART4(),
444                       POLY1305_BLOCK_PART5(),
445                       POLY1305_BLOCK_PART1(6 * 16),
446                       POLY1305_BLOCK_PART2())
447
448         # rounds 4,5
449         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
450                       POLY1305_BLOCK_PART3(),
451                       POLY1305_BLOCK_PART4(),
452                       POLY1305_BLOCK_PART5(),
453                       POLY1305_BLOCK_PART1(7 * 16))
454         vmovdqa (STACK_TMP)(%rsp), X15;
455         vmovdqa X8, (STACK_TMP)(%rsp);
456         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
457                       POLY1305_BLOCK_PART2(),
458                       POLY1305_BLOCK_PART3(),
459                       POLY1305_BLOCK_PART4(),
460                       POLY1305_BLOCK_PART5())
461         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
462                       POLY1305_BLOCK_PART1(8 * 16),
463                       POLY1305_BLOCK_PART2(),
464                       POLY1305_BLOCK_PART3(),
465                       POLY1305_BLOCK_PART4())
466         vmovdqa (STACK_TMP)(%rsp), X8;
467         vmovdqa X15, (STACK_TMP)(%rsp);
468         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
469                       POLY1305_BLOCK_PART5(),
470                       POLY1305_BLOCK_PART1(9 * 16),
471                       POLY1305_BLOCK_PART2(),
472                       POLY1305_BLOCK_PART3())
473
474         # rounds 6,7
475         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
476                       POLY1305_BLOCK_PART4(),
477                       POLY1305_BLOCK_PART5(),
478                       POLY1305_BLOCK_PART1(10 * 16),
479                       POLY1305_BLOCK_PART2())
480         vmovdqa (STACK_TMP)(%rsp), X15;
481         vmovdqa X8, (STACK_TMP)(%rsp);
482         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
483                       POLY1305_BLOCK_PART3(),
484                       POLY1305_BLOCK_PART4(),
485                       POLY1305_BLOCK_PART5(),
486                       POLY1305_BLOCK_PART1(11 * 16))
487         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
488                       POLY1305_BLOCK_PART2(),
489                       POLY1305_BLOCK_PART3(),
490                       POLY1305_BLOCK_PART4(),
491                       POLY1305_BLOCK_PART5())
492         vmovdqa (STACK_TMP)(%rsp), X8;
493         vmovdqa X15, (STACK_TMP)(%rsp);
494         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
495                       POLY1305_BLOCK_PART1(12 * 16),
496                       POLY1305_BLOCK_PART2(),
497                       POLY1305_BLOCK_PART3(),
498                       POLY1305_BLOCK_PART4())
499
500         # rounds 8,9
501         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
502                       POLY1305_BLOCK_PART5(),
503                       POLY1305_BLOCK_PART1(13 * 16),
504                       POLY1305_BLOCK_PART2(),
505                       POLY1305_BLOCK_PART3())
506         vmovdqa (STACK_TMP)(%rsp), X15;
507         vmovdqa X8, (STACK_TMP)(%rsp);
508         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
509                       POLY1305_BLOCK_PART4(),
510                       POLY1305_BLOCK_PART5(),
511                       POLY1305_BLOCK_PART1(14 * 16),
512                       POLY1305_BLOCK_PART2())
513         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
514                       POLY1305_BLOCK_PART3(),
515                       POLY1305_BLOCK_PART4(),
516                       POLY1305_BLOCK_PART5(),
517                       POLY1305_BLOCK_PART1(15 * 16))
518         vmovdqa (STACK_TMP)(%rsp), X8;
519         vmovdqa X15, (STACK_TMP)(%rsp);
520         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
521                       POLY1305_BLOCK_PART2(),
522                       POLY1305_BLOCK_PART3(),
523                       POLY1305_BLOCK_PART4(),
524                       POLY1305_BLOCK_PART5())
525
526         # rounds 10,11
527         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
528                       POLY1305_BLOCK_PART1(16 * 16),
529                       POLY1305_BLOCK_PART2(),
530                       POLY1305_BLOCK_PART3(),
531                       POLY1305_BLOCK_PART4())
532         vmovdqa (STACK_TMP)(%rsp), X15;
533         vmovdqa X8, (STACK_TMP)(%rsp);
534         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
535                       POLY1305_BLOCK_PART5(),
536                       POLY1305_BLOCK_PART1(17 * 16),
537                       POLY1305_BLOCK_PART2(),
538                       POLY1305_BLOCK_PART3())
539         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
540                       POLY1305_BLOCK_PART4(),
541                       POLY1305_BLOCK_PART5(),
542                       POLY1305_BLOCK_PART1(18 * 16),
543                       POLY1305_BLOCK_PART2())
544         vmovdqa (STACK_TMP)(%rsp), X8;
545         vmovdqa X15, (STACK_TMP)(%rsp);
546         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
547                       POLY1305_BLOCK_PART3(),
548                       POLY1305_BLOCK_PART4(),
549                       POLY1305_BLOCK_PART5(),
550                       POLY1305_BLOCK_PART1(19 * 16))
551
552         # rounds 12,13
553         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
554                       POLY1305_BLOCK_PART2(),
555                       POLY1305_BLOCK_PART3(),
556                       POLY1305_BLOCK_PART4(),
557                       POLY1305_BLOCK_PART5())
558         vmovdqa (STACK_TMP)(%rsp), X15;
559         vmovdqa X8, (STACK_TMP)(%rsp);
560         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
561                       POLY1305_BLOCK_PART1(20 * 16),
562                       POLY1305_BLOCK_PART2(),
563                       POLY1305_BLOCK_PART3(),
564                       POLY1305_BLOCK_PART4())
565         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
566                       POLY1305_BLOCK_PART5(),
567                       POLY1305_BLOCK_PART1(21 * 16),
568                       POLY1305_BLOCK_PART2(),
569                       POLY1305_BLOCK_PART3())
570         vmovdqa (STACK_TMP)(%rsp), X8;
571         vmovdqa X15, (STACK_TMP)(%rsp);
572         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
573                       POLY1305_BLOCK_PART4(),
574                       POLY1305_BLOCK_PART5(),
575                       POLY1305_BLOCK_PART1(22 * 16),
576                       POLY1305_BLOCK_PART2())
577
578         # rounds 14,15
579         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
580                       POLY1305_BLOCK_PART3(),
581                       POLY1305_BLOCK_PART4(),
582                       POLY1305_BLOCK_PART5(),
583                       POLY1305_BLOCK_PART1(23 * 16))
584         vmovdqa (STACK_TMP)(%rsp), X15;
585         vmovdqa X8, (STACK_TMP)(%rsp);
586         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
587                       POLY1305_BLOCK_PART2(),
588                       POLY1305_BLOCK_PART3(),
589                       POLY1305_BLOCK_PART4(),
590                       POLY1305_BLOCK_PART5())
591         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
592                       POLY1305_BLOCK_PART1(24 * 16),
593                       POLY1305_BLOCK_PART2(),
594                       POLY1305_BLOCK_PART3(),
595                       POLY1305_BLOCK_PART4())
596         vmovdqa (STACK_TMP)(%rsp), X8;
597         vmovdqa X15, (STACK_TMP)(%rsp);
598         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
599                       POLY1305_BLOCK_PART5(),
600                       POLY1305_BLOCK_PART1(25 * 16),
601                       POLY1305_BLOCK_PART2(),
602                       POLY1305_BLOCK_PART3())
603
604         # rounds 16,17
605         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
606                       POLY1305_BLOCK_PART4(),
607                       POLY1305_BLOCK_PART5(),
608                       POLY1305_BLOCK_PART1(26 * 16),
609                       POLY1305_BLOCK_PART2())
610         vmovdqa (STACK_TMP)(%rsp), X15;
611         vmovdqa X8, (STACK_TMP)(%rsp);
612         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
613                       POLY1305_BLOCK_PART3(),
614                       POLY1305_BLOCK_PART4(),
615                       POLY1305_BLOCK_PART5(),
616                       POLY1305_BLOCK_PART1(27 * 16))
617         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
618                       POLY1305_BLOCK_PART2(),
619                       POLY1305_BLOCK_PART3(),
620                       POLY1305_BLOCK_PART4(),
621                       POLY1305_BLOCK_PART5())
622         vmovdqa (STACK_TMP)(%rsp), X8;
623         vmovdqa X15, (STACK_TMP)(%rsp);
624         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
625                       POLY1305_BLOCK_PART1(28 * 16),
626                       POLY1305_BLOCK_PART2(),
627                       POLY1305_BLOCK_PART3(),
628                       POLY1305_BLOCK_PART4())
629
630         # rounds 18,19
631         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
632                       POLY1305_BLOCK_PART5(),
633                       POLY1305_BLOCK_PART1(29 * 16),
634                       POLY1305_BLOCK_PART2(),
635                       POLY1305_BLOCK_PART3())
636         vmovdqa (STACK_TMP)(%rsp), X15;
637         vmovdqa X8, (STACK_TMP)(%rsp);
638         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
639                       POLY1305_BLOCK_PART4(),
640                       POLY1305_BLOCK_PART5(),
641                       POLY1305_BLOCK_PART1(30 * 16),
642                       POLY1305_BLOCK_PART2())
643         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
644                       POLY1305_BLOCK_PART3(),
645                       POLY1305_BLOCK_PART4(),
646                       POLY1305_BLOCK_PART5(),
647                       POLY1305_BLOCK_PART1(31 * 16))
648         vmovdqa (STACK_TMP)(%rsp), X8;
649         vmovdqa X15, (STACK_TMP)(%rsp);
650         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
651                       POLY1305_BLOCK_PART2(),
652                       POLY1305_BLOCK_PART3(),
653                       POLY1305_BLOCK_PART4(),
654                       POLY1305_BLOCK_PART5())
655
656         movq (STACK_MAX + 5 * 8)(%rsp), SRC;
657         movq (STACK_MAX + 6 * 8)(%rsp), DST;
658
659         vmovdqa X8, (STACK_TMP1)(%rsp);
660
661         /* tmp := X15 */
662         vpbroadcastd (0 * 4)(INPUT), X15;
663         PLUS(X0, X15);
664         vpbroadcastd (1 * 4)(INPUT), X15;
665         PLUS(X1, X15);
666         vpbroadcastd (2 * 4)(INPUT), X15;
667         PLUS(X2, X15);
668         vpbroadcastd (3 * 4)(INPUT), X15;
669         PLUS(X3, X15);
670         vpbroadcastd (4 * 4)(INPUT), X15;
671         PLUS(X4, X15);
672         vpbroadcastd (5 * 4)(INPUT), X15;
673         PLUS(X5, X15);
674         vpbroadcastd (6 * 4)(INPUT), X15;
675         PLUS(X6, X15);
676         vpbroadcastd (7 * 4)(INPUT), X15;
677         PLUS(X7, X15);
678         transpose_4x4(X0, X1, X2, X3, X8, X15);
679         transpose_4x4(X4, X5, X6, X7, X8, X15);
680         vmovdqa (STACK_TMP1)(%rsp), X8;
681         transpose_16byte_2x2(X0, X4, X15);
682         transpose_16byte_2x2(X1, X5, X15);
683         transpose_16byte_2x2(X2, X6, X15);
684         transpose_16byte_2x2(X3, X7, X15);
685         vmovdqa (STACK_TMP)(%rsp), X15;
686         xor_src_dst(DST, SRC, (64 * 0 + 16 * 0), X0);
687         xor_src_dst(DST, SRC, (64 * 1 + 16 * 0), X1);
688         vpbroadcastd (8 * 4)(INPUT), X0;
689         PLUS(X8, X0);
690         vpbroadcastd (9 * 4)(INPUT), X0;
691         PLUS(X9, X0);
692         vpbroadcastd (10 * 4)(INPUT), X0;
693         PLUS(X10, X0);
694         vpbroadcastd (11 * 4)(INPUT), X0;
695         PLUS(X11, X0);
696         vmovdqa (STACK_VEC_X12)(%rsp), X0;
697         PLUS(X12, X0);
698         vmovdqa (STACK_VEC_X13)(%rsp), X0;
699         PLUS(X13, X0);
700         vpbroadcastd (14 * 4)(INPUT), X0;
701         PLUS(X14, X0);
702         vpbroadcastd (15 * 4)(INPUT), X0;
703         PLUS(X15, X0);
704         xor_src_dst(DST, SRC, (64 * 2 + 16 * 0), X2);
705         xor_src_dst(DST, SRC, (64 * 3 + 16 * 0), X3);
706
707         /* Update counter */
708         addq $8, (12 * 4)(INPUT);
709
710         transpose_4x4(X8, X9, X10, X11, X0, X1);
711         transpose_4x4(X12, X13, X14, X15, X0, X1);
712         xor_src_dst(DST, SRC, (64 * 4 + 16 * 0), X4);
713         xor_src_dst(DST, SRC, (64 * 5 + 16 * 0), X5);
714         transpose_16byte_2x2(X8, X12, X0);
715         transpose_16byte_2x2(X9, X13, X0);
716         transpose_16byte_2x2(X10, X14, X0);
717         transpose_16byte_2x2(X11, X15, X0);
718         xor_src_dst(DST, SRC, (64 * 6 + 16 * 0), X6);
719         xor_src_dst(DST, SRC, (64 * 7 + 16 * 0), X7);
720         xor_src_dst(DST, SRC, (64 * 0 + 16 * 2), X8);
721         xor_src_dst(DST, SRC, (64 * 1 + 16 * 2), X9);
722         xor_src_dst(DST, SRC, (64 * 2 + 16 * 2), X10);
723         xor_src_dst(DST, SRC, (64 * 3 + 16 * 2), X11);
724         xor_src_dst(DST, SRC, (64 * 4 + 16 * 2), X12);
725         xor_src_dst(DST, SRC, (64 * 5 + 16 * 2), X13);
726         xor_src_dst(DST, SRC, (64 * 6 + 16 * 2), X14);
727         xor_src_dst(DST, SRC, (64 * 7 + 16 * 2), X15);
728
729         subq $8, (STACK_MAX + 7 * 8)(%rsp); # NBLKS
730
731         lea (32 * 16)(POLY_RSRC), POLY_RSRC;
732         lea (8 * 64)(DST), DST;
733         lea (8 * 64)(SRC), SRC;
734         movq SRC, (STACK_MAX + 5 * 8)(%rsp);
735         movq DST, (STACK_MAX + 6 * 8)(%rsp);
736
737         jnz .Loop_poly8;
738
739         /* Store state */
740         POLY1305_STORE_STATE();
741
742         /* clear the used vector registers and stack */
743         vpxor X0, X0, X0;
744         vmovdqa X0, (STACK_VEC_X12)(%rsp);
745         vmovdqa X0, (STACK_VEC_X13)(%rsp);
746         vmovdqa X0, (STACK_TMP)(%rsp);
747         vmovdqa X0, (STACK_TMP1)(%rsp);
748         vzeroall;
749
750         movq (STACK_MAX + 0 * 8)(%rsp), %rbx;
751         movq (STACK_MAX + 1 * 8)(%rsp), %r12;
752         movq (STACK_MAX + 2 * 8)(%rsp), %r13;
753         movq (STACK_MAX + 3 * 8)(%rsp), %r14;
754         movq (STACK_MAX + 4 * 8)(%rsp), %r15;
755
756         xorl %eax, %eax;
757         leave;
758         ret;
759 ELF(.size _gcry_chacha20_poly1305_amd64_avx2_blocks8,
760           .-_gcry_chacha20_poly1305_amd64_avx2_blocks8;)
761
762 #endif /*defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS)*/
763 #endif /*__x86_64*/