pkgconfig: Fix libgcrypt.pc.
[libgcrypt.git] / cipher / chacha20-amd64-ssse3.S
1 /* chacha20-amd64-ssse3.S  -  SSSE3 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_SSSE3) && \
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 (16)
50 #define STACK_VEC_X13 (16 + STACK_VEC_X12)
51 #define STACK_TMP     (16 + STACK_VEC_X13)
52 #define STACK_TMP1    (16 + STACK_TMP)
53 #define STACK_TMP2    (16 + STACK_TMP1)
54
55 #define STACK_MAX     (16 + STACK_TMP2)
56
57 /* vector registers */
58 #define X0 %xmm0
59 #define X1 %xmm1
60 #define X2 %xmm2
61 #define X3 %xmm3
62 #define X4 %xmm4
63 #define X5 %xmm5
64 #define X6 %xmm6
65 #define X7 %xmm7
66 #define X8 %xmm8
67 #define X9 %xmm9
68 #define X10 %xmm10
69 #define X11 %xmm11
70 #define X12 %xmm12
71 #define X13 %xmm13
72 #define X14 %xmm14
73 #define X15 %xmm15
74
75 /**********************************************************************
76   helper macros
77  **********************************************************************/
78
79 /* 4x4 32-bit integer matrix transpose */
80 #define transpose_4x4(x0, x1, x2, x3, t1, t2, t3) \
81         movdqa    x0, t2; \
82         punpckhdq x1, t2; \
83         punpckldq x1, x0; \
84         \
85         movdqa    x2, t1; \
86         punpckldq x3, t1; \
87         punpckhdq x3, x2; \
88         \
89         movdqa     x0, x1; \
90         punpckhqdq t1, x1; \
91         punpcklqdq t1, x0; \
92         \
93         movdqa     t2, x3; \
94         punpckhqdq x2, x3; \
95         punpcklqdq x2, t2; \
96         movdqa     t2, x2;
97
98 /* fill xmm register with 32-bit value from memory */
99 #define pbroadcastd(mem32, xreg) \
100         movd mem32, xreg; \
101         pshufd $0, xreg, xreg;
102
103 /* xor with unaligned memory operand */
104 #define pxor_u(umem128, xreg, t) \
105         movdqu umem128, t; \
106         pxor t, xreg;
107
108 /* xor register with unaligned src and save to unaligned dst */
109 #define xor_src_dst(dst, src, offset, xreg, t) \
110         pxor_u(offset(src), xreg, t); \
111         movdqu xreg, offset(dst);
112
113 #define clear(x) pxor x,x;
114
115 /**********************************************************************
116   4-way chacha20
117  **********************************************************************/
118
119 #define ROTATE2(v1,v2,c,tmp1,tmp2)      \
120         movdqa v1, tmp1;                \
121         movdqa v2, tmp2;                \
122         psrld $(32 - (c)), v1;          \
123         pslld $(c), tmp1;               \
124         paddb tmp1, v1;                 \
125         psrld $(32 - (c)), v2;          \
126         pslld $(c), tmp2;               \
127         paddb tmp2, v2;
128
129 #define ROTATE_SHUF_2(v1,v2,shuf)       \
130         pshufb shuf, v1;                \
131         pshufb shuf, v2;
132
133 #define XOR(ds,s) \
134         pxor s, ds;
135
136 #define PLUS(ds,s) \
137         paddd s, ds;
138
139 #define QUARTERROUND2(a1,b1,c1,d1,a2,b2,c2,d2,ign,tmp1,tmp2,\
140                       interleave_op1,interleave_op2)            \
141         movdqa .Lshuf_rol16 rRIP, tmp1;                         \
142                 interleave_op1;                                 \
143         PLUS(a1,b1); PLUS(a2,b2); XOR(d1,a1); XOR(d2,a2);       \
144             ROTATE_SHUF_2(d1, d2, tmp1);                        \
145         PLUS(c1,d1); PLUS(c2,d2); XOR(b1,c1); XOR(b2,c2);       \
146             ROTATE2(b1, b2, 12, tmp1, tmp2);                    \
147         movdqa .Lshuf_rol8 rRIP, tmp1;                          \
148                 interleave_op2;                                 \
149         PLUS(a1,b1); PLUS(a2,b2); XOR(d1,a1); XOR(d2,a2);       \
150             ROTATE_SHUF_2(d1, d2, tmp1);                        \
151         PLUS(c1,d1); PLUS(c2,d2); XOR(b1,c1); XOR(b2,c2);       \
152             ROTATE2(b1, b2,  7, tmp1, tmp2);
153
154 chacha20_data:
155 .align 16
156 .Lshuf_rol16:
157         .byte 2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13
158 .Lshuf_rol8:
159         .byte 3,0,1,2,7,4,5,6,11,8,9,10,15,12,13,14
160 .Lcounter1:
161         .long 1,0,0,0
162 .Linc_counter:
163         .long 0,1,2,3
164 .Lunsigned_cmp:
165         .long 0x80000000,0x80000000,0x80000000,0x80000000
166
167 .align 8
168 .globl _gcry_chacha20_amd64_ssse3_blocks4
169 ELF(.type _gcry_chacha20_amd64_ssse3_blocks4,@function;)
170
171 _gcry_chacha20_amd64_ssse3_blocks4:
172         /* input:
173          *      %rdi: input
174          *      %rsi: dst
175          *      %rdx: src
176          *      %rcx: nblks (multiple of 4)
177          */
178         CFI_STARTPROC();
179
180         pushq %rbp;
181         CFI_PUSH(%rbp);
182         movq %rsp, %rbp;
183         CFI_DEF_CFA_REGISTER(%rbp);
184
185         subq $STACK_MAX, %rsp;
186         andq $~15, %rsp;
187
188 .Loop4:
189         mov $20, ROUND;
190
191         /* Construct counter vectors X12 and X13 */
192         movdqa .Linc_counter rRIP, X0;
193         movdqa .Lunsigned_cmp rRIP, X2;
194         pbroadcastd((12 * 4)(INPUT), X12);
195         pbroadcastd((13 * 4)(INPUT), X13);
196         paddd X0, X12;
197         movdqa X12, X1;
198         pxor X2, X0;
199         pxor X2, X1;
200         pcmpgtd X1, X0;
201         psubd X0, X13;
202         movdqa X12, (STACK_VEC_X12)(%rsp);
203         movdqa X13, (STACK_VEC_X13)(%rsp);
204
205         /* Load vectors */
206         pbroadcastd((0 * 4)(INPUT), X0);
207         pbroadcastd((1 * 4)(INPUT), X1);
208         pbroadcastd((2 * 4)(INPUT), X2);
209         pbroadcastd((3 * 4)(INPUT), X3);
210         pbroadcastd((4 * 4)(INPUT), X4);
211         pbroadcastd((5 * 4)(INPUT), X5);
212         pbroadcastd((6 * 4)(INPUT), X6);
213         pbroadcastd((7 * 4)(INPUT), X7);
214         pbroadcastd((8 * 4)(INPUT), X8);
215         pbroadcastd((9 * 4)(INPUT), X9);
216         pbroadcastd((10 * 4)(INPUT), X10);
217         pbroadcastd((11 * 4)(INPUT), X11);
218         pbroadcastd((14 * 4)(INPUT), X14);
219         pbroadcastd((15 * 4)(INPUT), X15);
220         movdqa X11, (STACK_TMP)(%rsp);
221         movdqa X15, (STACK_TMP1)(%rsp);
222
223 .Lround2_4:
224         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,,)
225         movdqa (STACK_TMP)(%rsp), X11;
226         movdqa (STACK_TMP1)(%rsp), X15;
227         movdqa X8, (STACK_TMP)(%rsp);
228         movdqa X9, (STACK_TMP1)(%rsp);
229         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,,)
230         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,,)
231         movdqa (STACK_TMP)(%rsp), X8;
232         movdqa (STACK_TMP1)(%rsp), X9;
233         movdqa X11, (STACK_TMP)(%rsp);
234         movdqa X15, (STACK_TMP1)(%rsp);
235         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,,)
236         sub $2, ROUND;
237         jnz .Lround2_4;
238
239         /* tmp := X15 */
240         movdqa (STACK_TMP)(%rsp), X11;
241         pbroadcastd((0 * 4)(INPUT), X15);
242         PLUS(X0, X15);
243         pbroadcastd((1 * 4)(INPUT), X15);
244         PLUS(X1, X15);
245         pbroadcastd((2 * 4)(INPUT), X15);
246         PLUS(X2, X15);
247         pbroadcastd((3 * 4)(INPUT), X15);
248         PLUS(X3, X15);
249         pbroadcastd((4 * 4)(INPUT), X15);
250         PLUS(X4, X15);
251         pbroadcastd((5 * 4)(INPUT), X15);
252         PLUS(X5, X15);
253         pbroadcastd((6 * 4)(INPUT), X15);
254         PLUS(X6, X15);
255         pbroadcastd((7 * 4)(INPUT), X15);
256         PLUS(X7, X15);
257         pbroadcastd((8 * 4)(INPUT), X15);
258         PLUS(X8, X15);
259         pbroadcastd((9 * 4)(INPUT), X15);
260         PLUS(X9, X15);
261         pbroadcastd((10 * 4)(INPUT), X15);
262         PLUS(X10, X15);
263         pbroadcastd((11 * 4)(INPUT), X15);
264         PLUS(X11, X15);
265         movdqa (STACK_VEC_X12)(%rsp), X15;
266         PLUS(X12, X15);
267         movdqa (STACK_VEC_X13)(%rsp), X15;
268         PLUS(X13, X15);
269         movdqa X13, (STACK_TMP)(%rsp);
270         pbroadcastd((14 * 4)(INPUT), X15);
271         PLUS(X14, X15);
272         movdqa (STACK_TMP1)(%rsp), X15;
273         movdqa X14, (STACK_TMP1)(%rsp);
274         pbroadcastd((15 * 4)(INPUT), X13);
275         PLUS(X15, X13);
276         movdqa X15, (STACK_TMP2)(%rsp);
277
278         /* Update counter */
279         addq $4, (12 * 4)(INPUT);
280
281         transpose_4x4(X0, X1, X2, X3, X13, X14, X15);
282         xor_src_dst(DST, SRC, (64 * 0 + 16 * 0), X0, X15);
283         xor_src_dst(DST, SRC, (64 * 1 + 16 * 0), X1, X15);
284         xor_src_dst(DST, SRC, (64 * 2 + 16 * 0), X2, X15);
285         xor_src_dst(DST, SRC, (64 * 3 + 16 * 0), X3, X15);
286         transpose_4x4(X4, X5, X6, X7, X0, X1, X2);
287         movdqa (STACK_TMP)(%rsp), X13;
288         movdqa (STACK_TMP1)(%rsp), X14;
289         movdqa (STACK_TMP2)(%rsp), X15;
290         xor_src_dst(DST, SRC, (64 * 0 + 16 * 1), X4, X0);
291         xor_src_dst(DST, SRC, (64 * 1 + 16 * 1), X5, X0);
292         xor_src_dst(DST, SRC, (64 * 2 + 16 * 1), X6, X0);
293         xor_src_dst(DST, SRC, (64 * 3 + 16 * 1), X7, X0);
294         transpose_4x4(X8, X9, X10, X11, X0, X1, X2);
295         xor_src_dst(DST, SRC, (64 * 0 + 16 * 2), X8, X0);
296         xor_src_dst(DST, SRC, (64 * 1 + 16 * 2), X9, X0);
297         xor_src_dst(DST, SRC, (64 * 2 + 16 * 2), X10, X0);
298         xor_src_dst(DST, SRC, (64 * 3 + 16 * 2), X11, X0);
299         transpose_4x4(X12, X13, X14, X15, X0, X1, X2);
300         xor_src_dst(DST, SRC, (64 * 0 + 16 * 3), X12, X0);
301         xor_src_dst(DST, SRC, (64 * 1 + 16 * 3), X13, X0);
302         xor_src_dst(DST, SRC, (64 * 2 + 16 * 3), X14, X0);
303         xor_src_dst(DST, SRC, (64 * 3 + 16 * 3), X15, X0);
304
305         sub $4, NBLKS;
306         lea (4 * 64)(DST), DST;
307         lea (4 * 64)(SRC), SRC;
308         jnz .Loop4;
309
310         /* clear the used vector registers and stack */
311         clear(X0);
312         movdqa X0, (STACK_VEC_X12)(%rsp);
313         movdqa X0, (STACK_VEC_X13)(%rsp);
314         movdqa X0, (STACK_TMP)(%rsp);
315         movdqa X0, (STACK_TMP1)(%rsp);
316         movdqa X0, (STACK_TMP2)(%rsp);
317         clear(X1);
318         clear(X2);
319         clear(X3);
320         clear(X4);
321         clear(X5);
322         clear(X6);
323         clear(X7);
324         clear(X8);
325         clear(X9);
326         clear(X10);
327         clear(X11);
328         clear(X12);
329         clear(X13);
330         clear(X14);
331         clear(X15);
332
333         /* eax zeroed by round loop. */
334         leave;
335         CFI_LEAVE();
336         ret;
337         CFI_ENDPROC();
338 ELF(.size _gcry_chacha20_amd64_ssse3_blocks4,
339           .-_gcry_chacha20_amd64_ssse3_blocks4;)
340
341 /**********************************************************************
342   2-way && 1-way chacha20
343  **********************************************************************/
344
345 #define ROTATE_SHUF(v1,shuf)            \
346         pshufb shuf, v1;
347
348 #define ROTATE(v1,c,tmp1)               \
349         movdqa v1, tmp1;                \
350         psrld $(32 - (c)), v1;          \
351         pslld $(c), tmp1;               \
352         paddb tmp1, v1;
353
354 #define WORD_SHUF(v1,shuf)              \
355         pshufd $shuf, v1, v1;
356
357 #define QUARTERROUND4(x0,x1,x2,x3,shuf_rol8,shuf_rol16,tmp1,shuf_x1,\
358                       shuf_x2,shuf_x3) \
359         PLUS(x0, x1); XOR(x3, x0); ROTATE_SHUF(x3, shuf_rol16); \
360         PLUS(x2, x3); XOR(x1, x2); ROTATE(x1, 12, tmp1); \
361         PLUS(x0, x1); XOR(x3, x0); ROTATE_SHUF(x3, shuf_rol8); \
362         PLUS(x2, x3); \
363           WORD_SHUF(x3, shuf_x3); \
364                       XOR(x1, x2); \
365           WORD_SHUF(x2, shuf_x2); \
366                                    ROTATE(x1, 7, tmp1); \
367           WORD_SHUF(x1, shuf_x1);
368
369 .align 8
370 .globl _gcry_chacha20_amd64_ssse3_blocks1
371 ELF(.type _gcry_chacha20_amd64_ssse3_blocks1,@function;)
372
373 _gcry_chacha20_amd64_ssse3_blocks1:
374         /* input:
375          *      %rdi: input
376          *      %rsi: dst
377          *      %rdx: src
378          *      %rcx: nblks
379          */
380         CFI_STARTPROC();
381
382         /* Load constants */
383         movdqa .Lcounter1 rRIP, X4;
384         movdqa .Lshuf_rol8 rRIP, X5;
385         movdqa .Lshuf_rol16 rRIP, X6;
386
387         /* Load state */
388         movdqu (0 * 4)(INPUT), X10;
389         movdqu (4 * 4)(INPUT), X11;
390         movdqu (8 * 4)(INPUT), X12;
391         movdqu (12 * 4)(INPUT), X13;
392
393         cmp $2, NBLKS;
394         jb .Loop1;
395
396         mov $20, ROUND;
397
398         movdqa X10, X0;
399         movdqa X11, X1;
400         movdqa X12, X2;
401         movdqa X13, X3;
402
403         movdqa X10, X8;
404         movdqa X11, X9;
405         movdqa X12, X14;
406         movdqa X13, X15;
407         paddq X4, X15;
408
409 .Lround2_2:
410         QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
411         QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
412         QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
413         QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
414         sub $2, ROUND;
415         jnz .Lround2_2;
416
417         PLUS(X0, X10);
418         PLUS(X1, X11);
419         PLUS(X2, X12);
420         PLUS(X3, X13);
421
422         /* Update counter */
423         paddq X4, X13;
424
425         PLUS(X8, X10);
426         PLUS(X9, X11);
427         PLUS(X14, X12);
428         PLUS(X15, X13);
429
430         /* Update counter */
431         paddq X4, X13;
432
433         xor_src_dst(DST, SRC, 0 * 4, X0, X7);
434         xor_src_dst(DST, SRC, 4 * 4, X1, X7);
435         xor_src_dst(DST, SRC, 8 * 4, X2, X7);
436         xor_src_dst(DST, SRC, 12 * 4, X3, X7);
437         xor_src_dst(DST, SRC, 16 * 4, X8, X7);
438         xor_src_dst(DST, SRC, 20 * 4, X9, X7);
439         xor_src_dst(DST, SRC, 24 * 4, X14, X7);
440         xor_src_dst(DST, SRC, 28 * 4, X15, X7);
441
442         lea (2 * 64)(DST), DST;
443         lea (2 * 64)(SRC), SRC;
444
445         clear(X8);
446         clear(X9);
447         clear(X14);
448         clear(X15);
449
450         sub $2, NBLKS;
451         jz .Ldone1;
452
453 .Loop1:
454         mov $20, ROUND;
455
456         movdqa X10, X0;
457         movdqa X11, X1;
458         movdqa X12, X2;
459         movdqa X13, X3;
460
461 .Lround2_1:
462         QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
463         QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
464         sub $2, ROUND;
465         jnz .Lround2_1;
466
467         PLUS(X0, X10);
468         PLUS(X1, X11);
469         PLUS(X2, X12);
470         PLUS(X3, X13);
471
472         /* Update counter */
473         paddq X4, X13;
474
475         xor_src_dst(DST, SRC, 0 * 4, X0, X7);
476         xor_src_dst(DST, SRC, 4 * 4, X1, X7);
477         xor_src_dst(DST, SRC, 8 * 4, X2, X7);
478         xor_src_dst(DST, SRC, 12 * 4, X3, X7);
479
480         lea (64)(DST), DST;
481         lea (64)(SRC), SRC;
482
483         sub $1, NBLKS;
484         jnz .Loop1;
485
486 .Ldone1:
487         /* Store counter */
488         movdqu X13, (12 * 4)(INPUT);
489
490         /* clear the used vector registers */
491         clear(X0);
492         clear(X1);
493         clear(X2);
494         clear(X3);
495         clear(X4);
496         clear(X5);
497         clear(X6);
498         clear(X7);
499         clear(X10);
500         clear(X11);
501         clear(X12);
502         clear(X13);
503
504         /* eax zeroed by round loop. */
505         ret;
506         CFI_ENDPROC();
507 ELF(.size _gcry_chacha20_amd64_ssse3_blocks1,
508           .-_gcry_chacha20_amd64_ssse3_blocks1;)
509
510 /**********************************************************************
511   4-way stitched chacha20-poly1305
512  **********************************************************************/
513
514 .align 8
515 .globl _gcry_chacha20_poly1305_amd64_ssse3_blocks4
516 ELF(.type _gcry_chacha20_poly1305_amd64_ssse3_blocks4,@function;)
517
518 _gcry_chacha20_poly1305_amd64_ssse3_blocks4:
519         /* input:
520          *      %rdi: input
521          *      %rsi: dst
522          *      %rdx: src
523          *      %rcx: nblks (multiple of 4)
524          *      %r9: poly1305-state
525          *      %r8: poly1305-src
526          */
527         CFI_STARTPROC();
528
529         pushq %rbp;
530         CFI_PUSH(%rbp);
531         movq %rsp, %rbp;
532         CFI_DEF_CFA_REGISTER(%rbp);
533
534         subq $(8 * 8) + STACK_MAX + 16, %rsp;
535         andq $~15, %rsp;
536
537         movq %rbx, (STACK_MAX + 0 * 8)(%rsp);
538         movq %r12, (STACK_MAX + 1 * 8)(%rsp);
539         movq %r13, (STACK_MAX + 2 * 8)(%rsp);
540         movq %r14, (STACK_MAX + 3 * 8)(%rsp);
541         movq %r15, (STACK_MAX + 4 * 8)(%rsp);
542         CFI_REG_ON_STACK(rbx, STACK_MAX + 0 * 8);
543         CFI_REG_ON_STACK(r12, STACK_MAX + 1 * 8);
544         CFI_REG_ON_STACK(r13, STACK_MAX + 2 * 8);
545         CFI_REG_ON_STACK(r14, STACK_MAX + 3 * 8);
546         CFI_REG_ON_STACK(r15, STACK_MAX + 4 * 8);
547
548         movq %rdx, (STACK_MAX + 5 * 8)(%rsp); # SRC
549         movq %rsi, (STACK_MAX + 6 * 8)(%rsp); # DST
550         movq %rcx, (STACK_MAX + 7 * 8)(%rsp); # NBLKS
551
552         /* Load state */
553         POLY1305_LOAD_STATE();
554
555 .Loop_poly4:
556
557         /* Construct counter vectors X12 and X13 */
558         movdqa .Linc_counter rRIP, X0;
559         movdqa .Lunsigned_cmp rRIP, X2;
560         pbroadcastd((12 * 4)(INPUT), X12);
561         pbroadcastd((13 * 4)(INPUT), X13);
562         paddd X0, X12;
563         movdqa X12, X1;
564         pxor X2, X0;
565         pxor X2, X1;
566         pcmpgtd X1, X0;
567         psubd X0, X13;
568         movdqa X12, (STACK_VEC_X12)(%rsp);
569         movdqa X13, (STACK_VEC_X13)(%rsp);
570
571         /* Load vectors */
572         pbroadcastd((0 * 4)(INPUT), X0);
573         pbroadcastd((1 * 4)(INPUT), X1);
574         pbroadcastd((2 * 4)(INPUT), X2);
575         pbroadcastd((3 * 4)(INPUT), X3);
576         pbroadcastd((4 * 4)(INPUT), X4);
577         pbroadcastd((5 * 4)(INPUT), X5);
578         pbroadcastd((6 * 4)(INPUT), X6);
579         pbroadcastd((7 * 4)(INPUT), X7);
580         pbroadcastd((8 * 4)(INPUT), X8);
581         pbroadcastd((9 * 4)(INPUT), X9);
582         pbroadcastd((10 * 4)(INPUT), X10);
583         pbroadcastd((11 * 4)(INPUT), X11);
584         pbroadcastd((14 * 4)(INPUT), X14);
585         pbroadcastd((15 * 4)(INPUT), X15);
586         movdqa X11, (STACK_TMP)(%rsp);
587         movdqa X15, (STACK_TMP1)(%rsp);
588
589         /* rounds 0,1 */
590         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,
591                       POLY1305_BLOCK_PART1(0 * 16),
592                       POLY1305_BLOCK_PART2())
593         movdqa (STACK_TMP)(%rsp), X11;
594         movdqa (STACK_TMP1)(%rsp), X15;
595         movdqa X8, (STACK_TMP)(%rsp);
596         movdqa X9, (STACK_TMP1)(%rsp);
597         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,
598                       POLY1305_BLOCK_PART3(),
599                       POLY1305_BLOCK_PART4())
600         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,
601                       POLY1305_BLOCK_PART5(),
602                       POLY1305_BLOCK_PART1(1 * 16))
603         movdqa (STACK_TMP)(%rsp), X8;
604         movdqa (STACK_TMP1)(%rsp), X9;
605         movdqa X11, (STACK_TMP)(%rsp);
606         movdqa X15, (STACK_TMP1)(%rsp);
607         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,
608                       POLY1305_BLOCK_PART2(),
609                       POLY1305_BLOCK_PART3())
610
611         /* rounds 2,3 */
612         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,
613                       POLY1305_BLOCK_PART4(),
614                       POLY1305_BLOCK_PART5())
615         movdqa (STACK_TMP)(%rsp), X11;
616         movdqa (STACK_TMP1)(%rsp), X15;
617         movdqa X8, (STACK_TMP)(%rsp);
618         movdqa X9, (STACK_TMP1)(%rsp);
619         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,
620                       POLY1305_BLOCK_PART1(2 * 16),
621                       POLY1305_BLOCK_PART2())
622         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,
623                       POLY1305_BLOCK_PART3(),
624                       POLY1305_BLOCK_PART4())
625         movdqa (STACK_TMP)(%rsp), X8;
626         movdqa (STACK_TMP1)(%rsp), X9;
627         movdqa X11, (STACK_TMP)(%rsp);
628         movdqa X15, (STACK_TMP1)(%rsp);
629         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,
630                       POLY1305_BLOCK_PART5(),
631                       POLY1305_BLOCK_PART1(3 * 16))
632
633         /* rounds 4,5 */
634         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,
635                       POLY1305_BLOCK_PART2(),
636                       POLY1305_BLOCK_PART3())
637         movdqa (STACK_TMP)(%rsp), X11;
638         movdqa (STACK_TMP1)(%rsp), X15;
639         movdqa X8, (STACK_TMP)(%rsp);
640         movdqa X9, (STACK_TMP1)(%rsp);
641         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,
642                       POLY1305_BLOCK_PART4(),
643                       POLY1305_BLOCK_PART5())
644         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,
645                       POLY1305_BLOCK_PART1(4 * 16),
646                       POLY1305_BLOCK_PART2())
647         movdqa (STACK_TMP)(%rsp), X8;
648         movdqa (STACK_TMP1)(%rsp), X9;
649         movdqa X11, (STACK_TMP)(%rsp);
650         movdqa X15, (STACK_TMP1)(%rsp);
651         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,
652                       POLY1305_BLOCK_PART3(),
653                       POLY1305_BLOCK_PART4())
654
655         /* rounds 6,7 */
656         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,
657                       POLY1305_BLOCK_PART5(),
658                       POLY1305_BLOCK_PART1(5 * 16))
659         movdqa (STACK_TMP)(%rsp), X11;
660         movdqa (STACK_TMP1)(%rsp), X15;
661         movdqa X8, (STACK_TMP)(%rsp);
662         movdqa X9, (STACK_TMP1)(%rsp);
663         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,
664                       POLY1305_BLOCK_PART2(),
665                       POLY1305_BLOCK_PART3())
666         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,
667                       POLY1305_BLOCK_PART4(),
668                       POLY1305_BLOCK_PART5())
669         movdqa (STACK_TMP)(%rsp), X8;
670         movdqa (STACK_TMP1)(%rsp), X9;
671         movdqa X11, (STACK_TMP)(%rsp);
672         movdqa X15, (STACK_TMP1)(%rsp);
673         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,
674                       POLY1305_BLOCK_PART1(6 * 16),
675                       POLY1305_BLOCK_PART2())
676
677         /* rounds 8,9 */
678         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,
679                       POLY1305_BLOCK_PART3(),
680                       POLY1305_BLOCK_PART4())
681         movdqa (STACK_TMP)(%rsp), X11;
682         movdqa (STACK_TMP1)(%rsp), X15;
683         movdqa X8, (STACK_TMP)(%rsp);
684         movdqa X9, (STACK_TMP1)(%rsp);
685         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,
686                       POLY1305_BLOCK_PART5(),
687                       POLY1305_BLOCK_PART1(7 * 16))
688         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,
689                       POLY1305_BLOCK_PART2(),
690                       POLY1305_BLOCK_PART3())
691         movdqa (STACK_TMP)(%rsp), X8;
692         movdqa (STACK_TMP1)(%rsp), X9;
693         movdqa X11, (STACK_TMP)(%rsp);
694         movdqa X15, (STACK_TMP1)(%rsp);
695         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,
696                       POLY1305_BLOCK_PART4(),
697                       POLY1305_BLOCK_PART5())
698
699         /* rounds 10,11 */
700         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,
701                       POLY1305_BLOCK_PART1(8 * 16),
702                       POLY1305_BLOCK_PART2())
703         movdqa (STACK_TMP)(%rsp), X11;
704         movdqa (STACK_TMP1)(%rsp), X15;
705         movdqa X8, (STACK_TMP)(%rsp);
706         movdqa X9, (STACK_TMP1)(%rsp);
707         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,
708                       POLY1305_BLOCK_PART3(),
709                       POLY1305_BLOCK_PART4())
710         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,
711                       POLY1305_BLOCK_PART5(),
712                       POLY1305_BLOCK_PART1(9 * 16))
713         movdqa (STACK_TMP)(%rsp), X8;
714         movdqa (STACK_TMP1)(%rsp), X9;
715         movdqa X11, (STACK_TMP)(%rsp);
716         movdqa X15, (STACK_TMP1)(%rsp);
717         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,
718                       POLY1305_BLOCK_PART2(),
719                       POLY1305_BLOCK_PART3())
720
721         /* rounds 12,13 */
722         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,
723                       POLY1305_BLOCK_PART4(),
724                       POLY1305_BLOCK_PART5())
725         movdqa (STACK_TMP)(%rsp), X11;
726         movdqa (STACK_TMP1)(%rsp), X15;
727         movdqa X8, (STACK_TMP)(%rsp);
728         movdqa X9, (STACK_TMP1)(%rsp);
729         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,
730                       POLY1305_BLOCK_PART1(10 * 16),
731                       POLY1305_BLOCK_PART2())
732         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,
733                       POLY1305_BLOCK_PART3(),
734                       POLY1305_BLOCK_PART4())
735         movdqa (STACK_TMP)(%rsp), X8;
736         movdqa (STACK_TMP1)(%rsp), X9;
737         movdqa X11, (STACK_TMP)(%rsp);
738         movdqa X15, (STACK_TMP1)(%rsp);
739         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,
740                       POLY1305_BLOCK_PART5(),
741                       POLY1305_BLOCK_PART1(11 * 16))
742
743         /* rounds 14,15 */
744         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,
745                       POLY1305_BLOCK_PART2(),
746                       POLY1305_BLOCK_PART3())
747         movdqa (STACK_TMP)(%rsp), X11;
748         movdqa (STACK_TMP1)(%rsp), X15;
749         movdqa X8, (STACK_TMP)(%rsp);
750         movdqa X9, (STACK_TMP1)(%rsp);
751         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,
752                       POLY1305_BLOCK_PART4(),
753                       POLY1305_BLOCK_PART5())
754         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,
755                       POLY1305_BLOCK_PART1(12 * 16),
756                       POLY1305_BLOCK_PART2())
757         movdqa (STACK_TMP)(%rsp), X8;
758         movdqa (STACK_TMP1)(%rsp), X9;
759         movdqa X11, (STACK_TMP)(%rsp);
760         movdqa X15, (STACK_TMP1)(%rsp);
761         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,
762                       POLY1305_BLOCK_PART3(),
763                       POLY1305_BLOCK_PART4())
764
765         /* rounds 16,17 */
766         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,
767                       POLY1305_BLOCK_PART5(),
768                       POLY1305_BLOCK_PART1(13 * 16))
769         movdqa (STACK_TMP)(%rsp), X11;
770         movdqa (STACK_TMP1)(%rsp), X15;
771         movdqa X8, (STACK_TMP)(%rsp);
772         movdqa X9, (STACK_TMP1)(%rsp);
773         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,
774                       POLY1305_BLOCK_PART2(),
775                       POLY1305_BLOCK_PART3())
776         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,
777                       POLY1305_BLOCK_PART4(),
778                       POLY1305_BLOCK_PART5())
779         movdqa (STACK_TMP)(%rsp), X8;
780         movdqa (STACK_TMP1)(%rsp), X9;
781         movdqa X11, (STACK_TMP)(%rsp);
782         movdqa X15, (STACK_TMP1)(%rsp);
783         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,
784                       POLY1305_BLOCK_PART1(14 * 16),
785                       POLY1305_BLOCK_PART2())
786
787         /* rounds 18,19 */
788         QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,
789                       POLY1305_BLOCK_PART3(),
790                       POLY1305_BLOCK_PART4())
791         movdqa (STACK_TMP)(%rsp), X11;
792         movdqa (STACK_TMP1)(%rsp), X15;
793         movdqa X8, (STACK_TMP)(%rsp);
794         movdqa X9, (STACK_TMP1)(%rsp);
795         QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,
796                       POLY1305_BLOCK_PART5(),
797                       POLY1305_BLOCK_PART1(15 * 16))
798         QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,
799                       POLY1305_BLOCK_PART2(),
800                       POLY1305_BLOCK_PART3())
801         movdqa (STACK_TMP)(%rsp), X8;
802         movdqa (STACK_TMP1)(%rsp), X9;
803         movdqa X11, (STACK_TMP)(%rsp);
804         movdqa X15, (STACK_TMP1)(%rsp);
805         QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,
806                       POLY1305_BLOCK_PART4(),
807                       POLY1305_BLOCK_PART5())
808
809         /* tmp := X15 */
810         movdqa (STACK_TMP)(%rsp), X11;
811         pbroadcastd((0 * 4)(INPUT), X15);
812         PLUS(X0, X15);
813         pbroadcastd((1 * 4)(INPUT), X15);
814         PLUS(X1, X15);
815         pbroadcastd((2 * 4)(INPUT), X15);
816         PLUS(X2, X15);
817         pbroadcastd((3 * 4)(INPUT), X15);
818         PLUS(X3, X15);
819         pbroadcastd((4 * 4)(INPUT), X15);
820         PLUS(X4, X15);
821         pbroadcastd((5 * 4)(INPUT), X15);
822         PLUS(X5, X15);
823         pbroadcastd((6 * 4)(INPUT), X15);
824         PLUS(X6, X15);
825         pbroadcastd((7 * 4)(INPUT), X15);
826         PLUS(X7, X15);
827         pbroadcastd((8 * 4)(INPUT), X15);
828         PLUS(X8, X15);
829         pbroadcastd((9 * 4)(INPUT), X15);
830         PLUS(X9, X15);
831         pbroadcastd((10 * 4)(INPUT), X15);
832         PLUS(X10, X15);
833         pbroadcastd((11 * 4)(INPUT), X15);
834         PLUS(X11, X15);
835         movdqa (STACK_VEC_X12)(%rsp), X15;
836         PLUS(X12, X15);
837         movdqa (STACK_VEC_X13)(%rsp), X15;
838         PLUS(X13, X15);
839         movdqa X13, (STACK_TMP)(%rsp);
840         pbroadcastd((14 * 4)(INPUT), X15);
841         PLUS(X14, X15);
842         movdqa (STACK_TMP1)(%rsp), X15;
843         movdqa X14, (STACK_TMP1)(%rsp);
844         pbroadcastd((15 * 4)(INPUT), X13);
845         PLUS(X15, X13);
846         movdqa X15, (STACK_TMP2)(%rsp);
847
848         /* Update counter */
849         addq $4, (12 * 4)(INPUT);
850
851         movq (STACK_MAX + 5 * 8)(%rsp), SRC;
852         movq (STACK_MAX + 6 * 8)(%rsp), DST;
853
854         transpose_4x4(X0, X1, X2, X3, X13, X14, X15);
855         xor_src_dst(DST, SRC, (64 * 0 + 16 * 0), X0, X15);
856         xor_src_dst(DST, SRC, (64 * 1 + 16 * 0), X1, X15);
857         xor_src_dst(DST, SRC, (64 * 2 + 16 * 0), X2, X15);
858         xor_src_dst(DST, SRC, (64 * 3 + 16 * 0), X3, X15);
859         transpose_4x4(X4, X5, X6, X7, X0, X1, X2);
860         movdqa (STACK_TMP)(%rsp), X13;
861         movdqa (STACK_TMP1)(%rsp), X14;
862         movdqa (STACK_TMP2)(%rsp), X15;
863         xor_src_dst(DST, SRC, (64 * 0 + 16 * 1), X4, X0);
864         xor_src_dst(DST, SRC, (64 * 1 + 16 * 1), X5, X0);
865         xor_src_dst(DST, SRC, (64 * 2 + 16 * 1), X6, X0);
866         xor_src_dst(DST, SRC, (64 * 3 + 16 * 1), X7, X0);
867         transpose_4x4(X8, X9, X10, X11, X0, X1, X2);
868         xor_src_dst(DST, SRC, (64 * 0 + 16 * 2), X8, X0);
869         xor_src_dst(DST, SRC, (64 * 1 + 16 * 2), X9, X0);
870         xor_src_dst(DST, SRC, (64 * 2 + 16 * 2), X10, X0);
871         xor_src_dst(DST, SRC, (64 * 3 + 16 * 2), X11, X0);
872         transpose_4x4(X12, X13, X14, X15, X0, X1, X2);
873         xor_src_dst(DST, SRC, (64 * 0 + 16 * 3), X12, X0);
874         xor_src_dst(DST, SRC, (64 * 1 + 16 * 3), X13, X0);
875         xor_src_dst(DST, SRC, (64 * 2 + 16 * 3), X14, X0);
876         xor_src_dst(DST, SRC, (64 * 3 + 16 * 3), X15, X0);
877
878         subq $4, (STACK_MAX + 7 * 8)(%rsp); # NBLKS
879
880         lea (16 * 16)(POLY_RSRC), POLY_RSRC;
881         lea (4 * 64)(DST), DST;
882         lea (4 * 64)(SRC), SRC;
883         movq SRC, (STACK_MAX + 5 * 8)(%rsp);
884         movq DST, (STACK_MAX + 6 * 8)(%rsp);
885
886         jnz .Loop_poly4;
887
888         /* Store state */
889         POLY1305_STORE_STATE();
890
891         /* clear the used vector registers and stack */
892         clear(X0);
893         movdqa X0, (STACK_VEC_X12)(%rsp);
894         movdqa X0, (STACK_VEC_X13)(%rsp);
895         movdqa X0, (STACK_TMP)(%rsp);
896         movdqa X0, (STACK_TMP1)(%rsp);
897         movdqa X0, (STACK_TMP2)(%rsp);
898         clear(X1);
899         clear(X2);
900         clear(X3);
901         clear(X4);
902         clear(X5);
903         clear(X6);
904         clear(X7);
905         clear(X8);
906         clear(X9);
907         clear(X10);
908         clear(X11);
909         clear(X12);
910         clear(X13);
911         clear(X14);
912         clear(X15);
913
914         movq (STACK_MAX + 0 * 8)(%rsp), %rbx;
915         movq (STACK_MAX + 1 * 8)(%rsp), %r12;
916         movq (STACK_MAX + 2 * 8)(%rsp), %r13;
917         movq (STACK_MAX + 3 * 8)(%rsp), %r14;
918         movq (STACK_MAX + 4 * 8)(%rsp), %r15;
919         CFI_RESTORE(%rbx);
920         CFI_RESTORE(%r12);
921         CFI_RESTORE(%r13);
922         CFI_RESTORE(%r14);
923         CFI_RESTORE(%r15);
924
925         xorl %eax, %eax;
926         leave;
927         CFI_LEAVE();
928         ret;
929         CFI_ENDPROC();
930 ELF(.size _gcry_chacha20_poly1305_amd64_ssse3_blocks4,
931           .-_gcry_chacha20_poly1305_amd64_ssse3_blocks4;)
932
933 /**********************************************************************
934   2-way && 1-way stitched chacha20-poly1305
935  **********************************************************************/
936
937 .align 8
938 .globl _gcry_chacha20_poly1305_amd64_ssse3_blocks1
939 ELF(.type _gcry_chacha20_poly1305_amd64_ssse3_blocks1,@function;)
940
941 _gcry_chacha20_poly1305_amd64_ssse3_blocks1:
942         /* input:
943          *      %rdi: chacha20-state
944          *      %rsi: dst
945          *      %rdx: src
946          *      %rcx: nblks
947          *      %r9: poly1305-state
948          *      %r8: poly1305-src
949          */
950         CFI_STARTPROC();
951
952         pushq %rbp;
953         CFI_PUSH(%rbp);
954         movq %rsp, %rbp;
955         CFI_DEF_CFA_REGISTER(%rbp);
956
957         subq $(8 * 8), %rsp;
958         movq %rbx, (0 * 8)(%rsp);
959         movq %r12, (1 * 8)(%rsp);
960         movq %r13, (2 * 8)(%rsp);
961         movq %r14, (3 * 8)(%rsp);
962         movq %r15, (4 * 8)(%rsp);
963         CFI_REG_ON_STACK(rbx, 0 * 8);
964         CFI_REG_ON_STACK(r12, 1 * 8);
965         CFI_REG_ON_STACK(r13, 2 * 8);
966         CFI_REG_ON_STACK(r14, 3 * 8);
967         CFI_REG_ON_STACK(r15, 4 * 8);
968
969         movq %rdx, (5 * 8)(%rsp); # SRC
970         movq %rsi, (6 * 8)(%rsp); # DST
971         movq %rcx, (7 * 8)(%rsp); # NBLKS
972
973         /* Load constants */
974         movdqa .Lcounter1 rRIP, X4;
975         movdqa .Lshuf_rol8 rRIP, X5;
976         movdqa .Lshuf_rol16 rRIP, X6;
977
978         /* Load state */
979         movdqu (0 * 4)(INPUT), X10;
980         movdqu (4 * 4)(INPUT), X11;
981         movdqu (8 * 4)(INPUT), X12;
982         movdqu (12 * 4)(INPUT), X13;
983
984         POLY1305_LOAD_STATE();
985
986         cmpq $2, (7 * 8)(%rsp); #NBLKS
987         jb .Loop_poly1;
988
989         movdqa X10, X0;
990         movdqa X11, X1;
991         movdqa X12, X2;
992         movdqa X13, X3;
993
994         movdqa X10, X8;
995         movdqa X11, X9;
996         movdqa X12, X14;
997         movdqa X13, X15;
998         paddq X4, X15;
999
1000         /* Process two ChaCha20 blocks and eight Poly1305 blocks. */
1001
1002         POLY1305_BLOCK_PART1(0 * 16);
1003           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
1004         POLY1305_BLOCK_PART2();
1005           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
1006         POLY1305_BLOCK_PART3();
1007           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
1008         POLY1305_BLOCK_PART4();
1009           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
1010
1011         POLY1305_BLOCK_PART5();
1012           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
1013         POLY1305_BLOCK_PART1(1 * 16);
1014           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
1015         POLY1305_BLOCK_PART2();
1016           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
1017         POLY1305_BLOCK_PART3();
1018           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
1019
1020         POLY1305_BLOCK_PART4();
1021           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
1022         POLY1305_BLOCK_PART5();
1023           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
1024         POLY1305_BLOCK_PART1(2 * 16);
1025           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
1026         POLY1305_BLOCK_PART2();
1027           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
1028
1029         POLY1305_BLOCK_PART3();
1030           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
1031         POLY1305_BLOCK_PART4();
1032           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
1033         POLY1305_BLOCK_PART5();
1034           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
1035         POLY1305_BLOCK_PART1(3 * 16);
1036           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
1037
1038         POLY1305_BLOCK_PART2();
1039           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
1040         POLY1305_BLOCK_PART3();
1041           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
1042         POLY1305_BLOCK_PART4();
1043           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
1044         POLY1305_BLOCK_PART5();
1045           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
1046
1047         POLY1305_BLOCK_PART1(4 * 16);
1048           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
1049         POLY1305_BLOCK_PART2();
1050           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
1051         POLY1305_BLOCK_PART3();
1052           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
1053         POLY1305_BLOCK_PART4();
1054           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
1055
1056         POLY1305_BLOCK_PART5();
1057           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
1058         POLY1305_BLOCK_PART1(5 * 16);
1059           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
1060         POLY1305_BLOCK_PART2();
1061           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
1062         POLY1305_BLOCK_PART3();
1063           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
1064
1065         POLY1305_BLOCK_PART4();
1066           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
1067         POLY1305_BLOCK_PART5();
1068           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
1069         POLY1305_BLOCK_PART1(6 * 16);
1070           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
1071         POLY1305_BLOCK_PART2();
1072           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
1073
1074         POLY1305_BLOCK_PART3();
1075           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
1076         POLY1305_BLOCK_PART4();
1077           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
1078         POLY1305_BLOCK_PART5();
1079           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
1080         POLY1305_BLOCK_PART1(7 * 16);
1081           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
1082
1083         POLY1305_BLOCK_PART2();
1084           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
1085         POLY1305_BLOCK_PART3();
1086           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
1087         POLY1305_BLOCK_PART4();
1088           QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
1089         POLY1305_BLOCK_PART5();
1090           QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
1091
1092         movq (5 * 8)(%rsp), SRC;
1093         movq (6 * 8)(%rsp), DST;
1094
1095         PLUS(X0, X10);
1096         PLUS(X1, X11);
1097         PLUS(X2, X12);
1098         PLUS(X3, X13);
1099
1100         /* Update counter */
1101         paddq X4, X13;
1102
1103         PLUS(X8, X10);
1104         PLUS(X9, X11);
1105         PLUS(X14, X12);
1106         PLUS(X15, X13);
1107
1108         /* Update counter */
1109         paddq X4, X13;
1110
1111         xor_src_dst(DST, SRC, 0 * 4, X0, X7);
1112         xor_src_dst(DST, SRC, 4 * 4, X1, X7);
1113         xor_src_dst(DST, SRC, 8 * 4, X2, X7);
1114         xor_src_dst(DST, SRC, 12 * 4, X3, X7);
1115         xor_src_dst(DST, SRC, 16 * 4, X8, X7);
1116         xor_src_dst(DST, SRC, 20 * 4, X9, X7);
1117         xor_src_dst(DST, SRC, 24 * 4, X14, X7);
1118         xor_src_dst(DST, SRC, 28 * 4, X15, X7);
1119
1120         clear(X8);
1121         clear(X9);
1122         clear(X14);
1123         clear(X15);
1124
1125         subq $2, (7 * 8)(%rsp); # NBLKS
1126         lea (2 * 64)(POLY_RSRC), POLY_RSRC;
1127         lea (2 * 64)(SRC), SRC;
1128         lea (2 * 64)(DST), DST;
1129         movq SRC, (5 * 8)(%rsp);
1130         movq DST, (6 * 8)(%rsp);
1131         jz .Ldone_poly1;
1132
1133 .Loop_poly1:
1134         movdqa X10, X0;
1135         movdqa X11, X1;
1136         movdqa X12, X2;
1137         movdqa X13, X3;
1138
1139         /* Process one ChaCha20 block and four Poly1305 blocks. */
1140         POLY1305_BLOCK_PART1(0 * 16);
1141           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
1142         POLY1305_BLOCK_PART2();
1143           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
1144
1145         POLY1305_BLOCK_PART3();
1146           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
1147         POLY1305_BLOCK_PART4();
1148           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
1149
1150         POLY1305_BLOCK_PART5();
1151           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
1152         POLY1305_BLOCK_PART1(1 * 16);
1153           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
1154
1155         POLY1305_BLOCK_PART2();
1156           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
1157         POLY1305_BLOCK_PART3();
1158           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
1159
1160         POLY1305_BLOCK_PART4();
1161           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
1162         POLY1305_BLOCK_PART5();
1163           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
1164
1165         POLY1305_BLOCK_PART1(2 * 16);
1166           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
1167         POLY1305_BLOCK_PART2();
1168           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
1169
1170         POLY1305_BLOCK_PART3();
1171           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
1172         POLY1305_BLOCK_PART4();
1173           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
1174
1175         POLY1305_BLOCK_PART5();
1176           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
1177         POLY1305_BLOCK_PART1(3 * 16);
1178           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
1179
1180         POLY1305_BLOCK_PART2();
1181           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
1182         POLY1305_BLOCK_PART3();
1183           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
1184
1185         POLY1305_BLOCK_PART4();
1186           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
1187         POLY1305_BLOCK_PART5();
1188           QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
1189
1190         movq (5 * 8)(%rsp), SRC;
1191         movq (6 * 8)(%rsp), DST;
1192
1193         PLUS(X0, X10);
1194         PLUS(X1, X11);
1195         PLUS(X2, X12);
1196         PLUS(X3, X13);
1197
1198         /* Update counter */
1199         paddq X4, X13;
1200
1201         xor_src_dst(DST, SRC, 0 * 4, X0, X7);
1202         xor_src_dst(DST, SRC, 4 * 4, X1, X7);
1203         xor_src_dst(DST, SRC, 8 * 4, X2, X7);
1204         xor_src_dst(DST, SRC, 12 * 4, X3, X7);
1205
1206         subq $1, (7 * 8)(%rsp); # NBLKS
1207         lea (64)(POLY_RSRC), POLY_RSRC;
1208         lea (64)(SRC), SRC;
1209         lea (64)(DST), DST;
1210         movq SRC, (5 * 8)(%rsp);
1211         movq DST, (6 * 8)(%rsp);
1212
1213         jnz .Loop_poly1;
1214
1215 .Ldone_poly1:
1216         /* Store state */
1217         POLY1305_STORE_STATE();
1218
1219         movdqu X13, (12 * 4)(INPUT);
1220
1221         /* clear the used vector registers */
1222         clear(X0);
1223         clear(X1);
1224         clear(X2);
1225         clear(X3);
1226         clear(X4);
1227         clear(X5);
1228         clear(X6);
1229         clear(X7);
1230         clear(X10);
1231         clear(X11);
1232         clear(X12);
1233         clear(X13);
1234
1235         movq (0 * 8)(%rsp), %rbx;
1236         movq (1 * 8)(%rsp), %r12;
1237         movq (2 * 8)(%rsp), %r13;
1238         movq (3 * 8)(%rsp), %r14;
1239         movq (4 * 8)(%rsp), %r15;
1240         CFI_RESTORE(%rbx);
1241         CFI_RESTORE(%r12);
1242         CFI_RESTORE(%r13);
1243         CFI_RESTORE(%r14);
1244         CFI_RESTORE(%r15);
1245
1246         xorl %eax, %eax;
1247         leave;
1248         CFI_LEAVE();
1249         ret;
1250         CFI_ENDPROC();
1251 ELF(.size _gcry_chacha20_poly1305_amd64_ssse3_blocks1,
1252           .-_gcry_chacha20_poly1305_amd64_ssse3_blocks1;)
1253
1254 #endif /*defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS)*/
1255 #endif /*__x86_64*/