pkgconfig: Fix libgcrypt.pc.
[libgcrypt.git] / cipher / twofish-avx2-amd64.S
1 /* twofish-avx2-amd64.S  -  AMD64/AVX2 assembly implementation of Twofish cipher
2  *
3  * Copyright (C) 2013-2017 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 #ifdef __x86_64
22 #include <config.h>
23 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
24     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && defined(USE_TWOFISH) && \
25     defined(ENABLE_AVX2_SUPPORT)
26
27 #include "asm-common-amd64.h"
28
29 .text
30
31 /* structure of TWOFISH_context: */
32 #define s0      0
33 #define s1      ((s0) + 4 * 256)
34 #define s2      ((s1) + 4 * 256)
35 #define s3      ((s2) + 4 * 256)
36 #define w       ((s3) + 4 * 256)
37 #define k       ((w) + 4 * 8)
38
39 /* register macros */
40 #define CTX     %rdi
41
42 #define RROUND  %rbp
43 #define RROUNDd %ebp
44 #define RS0     CTX
45 #define RS1     %r8
46 #define RS2     %r9
47 #define RS3     %r10
48 #define RK      %r11
49 #define RW      %rax
50
51 #define RA0     %ymm8
52 #define RB0     %ymm9
53 #define RC0     %ymm10
54 #define RD0     %ymm11
55 #define RA1     %ymm12
56 #define RB1     %ymm13
57 #define RC1     %ymm14
58 #define RD1     %ymm15
59
60 /* temp regs */
61 #define RX0     %ymm0
62 #define RY0     %ymm1
63 #define RX1     %ymm2
64 #define RY1     %ymm3
65 #define RT0     %ymm4
66 #define RIDX    %ymm5
67
68 #define RX0x    %xmm0
69 #define RY0x    %xmm1
70 #define RX1x    %xmm2
71 #define RY1x    %xmm3
72 #define RT0x    %xmm4
73 #define RIDXx   %xmm5
74
75 #define RTMP0   RX0
76 #define RTMP0x  RX0x
77 #define RTMP1   RX1
78 #define RTMP1x  RX1x
79 #define RTMP2   RY0
80 #define RTMP2x  RY0x
81 #define RTMP3   RY1
82 #define RTMP3x  RY1x
83 #define RTMP4   RIDX
84 #define RTMP4x  RIDXx
85
86 /* vpgatherdd mask and '-1' */
87 #define RNOT    %ymm6
88 #define RNOTx   %xmm6
89
90 /* byte mask, (-1 >> 24) */
91 #define RBYTE   %ymm7
92
93 /**********************************************************************
94   16-way AVX2 twofish
95  **********************************************************************/
96 #define init_round_constants() \
97         vpcmpeqd RNOT, RNOT, RNOT; \
98         leaq k(CTX), RK; \
99         leaq w(CTX), RW; \
100         vpsrld $24, RNOT, RBYTE; \
101         leaq s1(CTX), RS1; \
102         leaq s2(CTX), RS2; \
103         leaq s3(CTX), RS3; \
104
105 #define g16(ab, rs0, rs1, rs2, rs3, xy) \
106         vpand RBYTE, ab ## 0, RIDX; \
107         vpgatherdd RNOT, (rs0, RIDX, 4), xy ## 0; \
108         vpcmpeqd RNOT, RNOT, RNOT; \
109                 \
110                 vpand RBYTE, ab ## 1, RIDX; \
111                 vpgatherdd RNOT, (rs0, RIDX, 4), xy ## 1; \
112                 vpcmpeqd RNOT, RNOT, RNOT; \
113         \
114         vpsrld $8, ab ## 0, RIDX; \
115         vpand RBYTE, RIDX, RIDX; \
116         vpgatherdd RNOT, (rs1, RIDX, 4), RT0; \
117         vpcmpeqd RNOT, RNOT, RNOT; \
118         vpxor RT0, xy ## 0, xy ## 0; \
119                 \
120                 vpsrld $8, ab ## 1, RIDX; \
121                 vpand RBYTE, RIDX, RIDX; \
122                 vpgatherdd RNOT, (rs1, RIDX, 4), RT0; \
123                 vpcmpeqd RNOT, RNOT, RNOT; \
124                 vpxor RT0, xy ## 1, xy ## 1; \
125         \
126         vpsrld $16, ab ## 0, RIDX; \
127         vpand RBYTE, RIDX, RIDX; \
128         vpgatherdd RNOT, (rs2, RIDX, 4), RT0; \
129         vpcmpeqd RNOT, RNOT, RNOT; \
130         vpxor RT0, xy ## 0, xy ## 0; \
131                 \
132                 vpsrld $16, ab ## 1, RIDX; \
133                 vpand RBYTE, RIDX, RIDX; \
134                 vpgatherdd RNOT, (rs2, RIDX, 4), RT0; \
135                 vpcmpeqd RNOT, RNOT, RNOT; \
136                 vpxor RT0, xy ## 1, xy ## 1; \
137         \
138         vpsrld $24, ab ## 0, RIDX; \
139         vpgatherdd RNOT, (rs3, RIDX, 4), RT0; \
140         vpcmpeqd RNOT, RNOT, RNOT; \
141         vpxor RT0, xy ## 0, xy ## 0; \
142                 \
143                 vpsrld $24, ab ## 1, RIDX; \
144                 vpgatherdd RNOT, (rs3, RIDX, 4), RT0; \
145                 vpcmpeqd RNOT, RNOT, RNOT; \
146                 vpxor RT0, xy ## 1, xy ## 1;
147
148 #define g1_16(a, x) \
149         g16(a, RS0, RS1, RS2, RS3, x);
150
151 #define g2_16(b, y) \
152         g16(b, RS1, RS2, RS3, RS0, y);
153
154 #define encrypt_round_end16(a, b, c, d, nk, r) \
155         vpaddd RY0, RX0, RX0; \
156         vpaddd RX0, RY0, RY0; \
157         vpbroadcastd ((nk)+((r)*8))(RK), RT0; \
158         vpaddd RT0, RX0, RX0; \
159         vpbroadcastd 4+((nk)+((r)*8))(RK), RT0; \
160         vpaddd RT0, RY0, RY0; \
161         \
162         vpxor RY0, d ## 0, d ## 0; \
163         \
164         vpxor RX0, c ## 0, c ## 0; \
165         vpsrld $1, c ## 0, RT0; \
166         vpslld $31, c ## 0, c ## 0; \
167         vpor RT0, c ## 0, c ## 0; \
168         \
169                 vpaddd RY1, RX1, RX1; \
170                 vpaddd RX1, RY1, RY1; \
171                 vpbroadcastd ((nk)+((r)*8))(RK), RT0; \
172                 vpaddd RT0, RX1, RX1; \
173                 vpbroadcastd 4+((nk)+((r)*8))(RK), RT0; \
174                 vpaddd RT0, RY1, RY1; \
175                 \
176                 vpxor RY1, d ## 1, d ## 1; \
177                 \
178                 vpxor RX1, c ## 1, c ## 1; \
179                 vpsrld $1, c ## 1, RT0; \
180                 vpslld $31, c ## 1, c ## 1; \
181                 vpor RT0, c ## 1, c ## 1; \
182
183 #define encrypt_round16(a, b, c, d, nk, r) \
184         g2_16(b, RY); \
185         \
186         vpslld $1, b ## 0, RT0; \
187         vpsrld $31, b ## 0, b ## 0; \
188         vpor RT0, b ## 0, b ## 0; \
189         \
190                 vpslld $1, b ## 1, RT0; \
191                 vpsrld $31, b ## 1, b ## 1; \
192                 vpor RT0, b ## 1, b ## 1; \
193         \
194         g1_16(a, RX); \
195         \
196         encrypt_round_end16(a, b, c, d, nk, r);
197
198 #define encrypt_round_first16(a, b, c, d, nk, r) \
199         vpslld $1, d ## 0, RT0; \
200         vpsrld $31, d ## 0, d ## 0; \
201         vpor RT0, d ## 0, d ## 0; \
202         \
203                 vpslld $1, d ## 1, RT0; \
204                 vpsrld $31, d ## 1, d ## 1; \
205                 vpor RT0, d ## 1, d ## 1; \
206         \
207         encrypt_round16(a, b, c, d, nk, r);
208
209 #define encrypt_round_last16(a, b, c, d, nk, r) \
210         g2_16(b, RY); \
211         \
212         g1_16(a, RX); \
213         \
214         encrypt_round_end16(a, b, c, d, nk, r);
215
216 #define decrypt_round_end16(a, b, c, d, nk, r) \
217         vpaddd RY0, RX0, RX0; \
218         vpaddd RX0, RY0, RY0; \
219         vpbroadcastd ((nk)+((r)*8))(RK), RT0; \
220         vpaddd RT0, RX0, RX0; \
221         vpbroadcastd 4+((nk)+((r)*8))(RK), RT0; \
222         vpaddd RT0, RY0, RY0; \
223         \
224         vpxor RX0, c ## 0, c ## 0; \
225         \
226         vpxor RY0, d ## 0, d ## 0; \
227         vpsrld $1, d ## 0, RT0; \
228         vpslld $31, d ## 0, d ## 0; \
229         vpor RT0, d ## 0, d ## 0; \
230         \
231                 vpaddd RY1, RX1, RX1; \
232                 vpaddd RX1, RY1, RY1; \
233                 vpbroadcastd ((nk)+((r)*8))(RK), RT0; \
234                 vpaddd RT0, RX1, RX1; \
235                 vpbroadcastd 4+((nk)+((r)*8))(RK), RT0; \
236                 vpaddd RT0, RY1, RY1; \
237                 \
238                 vpxor RX1, c ## 1, c ## 1; \
239                 \
240                 vpxor RY1, d ## 1, d ## 1; \
241                 vpsrld $1, d ## 1, RT0; \
242                 vpslld $31, d ## 1, d ## 1; \
243                 vpor RT0, d ## 1, d ## 1;
244
245 #define decrypt_round16(a, b, c, d, nk, r) \
246         g1_16(a, RX); \
247         \
248         vpslld $1, a ## 0, RT0; \
249         vpsrld $31, a ## 0, a ## 0; \
250         vpor RT0, a ## 0, a ## 0; \
251         \
252                 vpslld $1, a ## 1, RT0; \
253                 vpsrld $31, a ## 1, a ## 1; \
254                 vpor RT0, a ## 1, a ## 1; \
255         \
256         g2_16(b, RY); \
257         \
258         decrypt_round_end16(a, b, c, d, nk, r);
259
260 #define decrypt_round_first16(a, b, c, d, nk, r) \
261         vpslld $1, c ## 0, RT0; \
262         vpsrld $31, c ## 0, c ## 0; \
263         vpor RT0, c ## 0, c ## 0; \
264         \
265                 vpslld $1, c ## 1, RT0; \
266                 vpsrld $31, c ## 1, c ## 1; \
267                 vpor RT0, c ## 1, c ## 1; \
268         \
269         decrypt_round16(a, b, c, d, nk, r)
270
271 #define decrypt_round_last16(a, b, c, d, nk, r) \
272         g1_16(a, RX); \
273         \
274         g2_16(b, RY); \
275         \
276         decrypt_round_end16(a, b, c, d, nk, r);
277
278 #define encrypt_cycle16(r) \
279         encrypt_round16(RA, RB, RC, RD, 0, r); \
280         encrypt_round16(RC, RD, RA, RB, 8, r);
281
282 #define encrypt_cycle_first16(r) \
283         encrypt_round_first16(RA, RB, RC, RD, 0, r); \
284         encrypt_round16(RC, RD, RA, RB, 8, r);
285
286 #define encrypt_cycle_last16(r) \
287         encrypt_round16(RA, RB, RC, RD, 0, r); \
288         encrypt_round_last16(RC, RD, RA, RB, 8, r);
289
290 #define decrypt_cycle16(r) \
291         decrypt_round16(RC, RD, RA, RB, 8, r); \
292         decrypt_round16(RA, RB, RC, RD, 0, r);
293
294 #define decrypt_cycle_first16(r) \
295         decrypt_round_first16(RC, RD, RA, RB, 8, r); \
296         decrypt_round16(RA, RB, RC, RD, 0, r);
297
298 #define decrypt_cycle_last16(r) \
299         decrypt_round16(RC, RD, RA, RB, 8, r); \
300         decrypt_round_last16(RA, RB, RC, RD, 0, r);
301
302 #define transpose_4x4(x0,x1,x2,x3,t1,t2) \
303         vpunpckhdq x1, x0, t2; \
304         vpunpckldq x1, x0, x0; \
305         \
306         vpunpckldq x3, x2, t1; \
307         vpunpckhdq x3, x2, x2; \
308         \
309         vpunpckhqdq t1, x0, x1; \
310         vpunpcklqdq t1, x0, x0; \
311         \
312         vpunpckhqdq x2, t2, x3; \
313         vpunpcklqdq x2, t2, x2;
314
315 #define read_blocks8(offs,a,b,c,d) \
316         vmovdqu 16*offs(RIO), a; \
317         vmovdqu 16*offs+32(RIO), b; \
318         vmovdqu 16*offs+64(RIO), c; \
319         vmovdqu 16*offs+96(RIO), d; \
320         \
321         transpose_4x4(a, b, c, d, RX0, RY0);
322
323 #define write_blocks8(offs,a,b,c,d) \
324         transpose_4x4(a, b, c, d, RX0, RY0); \
325         \
326         vmovdqu a, 16*offs(RIO); \
327         vmovdqu b, 16*offs+32(RIO); \
328         vmovdqu c, 16*offs+64(RIO); \
329         vmovdqu d, 16*offs+96(RIO);
330
331 #define inpack_enc8(a,b,c,d) \
332         vpbroadcastd 4*0(RW), RT0; \
333         vpxor RT0, a, a; \
334         \
335         vpbroadcastd 4*1(RW), RT0; \
336         vpxor RT0, b, b; \
337         \
338         vpbroadcastd 4*2(RW), RT0; \
339         vpxor RT0, c, c; \
340         \
341         vpbroadcastd 4*3(RW), RT0; \
342         vpxor RT0, d, d;
343
344 #define outunpack_enc8(a,b,c,d) \
345         vpbroadcastd 4*4(RW), RX0; \
346         vpbroadcastd 4*5(RW), RY0; \
347         vpxor RX0, c, RX0; \
348         vpxor RY0, d, RY0; \
349         \
350         vpbroadcastd 4*6(RW), RT0; \
351         vpxor RT0, a, c; \
352         vpbroadcastd 4*7(RW), RT0; \
353         vpxor RT0, b, d; \
354         \
355         vmovdqa RX0, a; \
356         vmovdqa RY0, b;
357
358 #define inpack_dec8(a,b,c,d) \
359         vpbroadcastd 4*4(RW), RX0; \
360         vpbroadcastd 4*5(RW), RY0; \
361         vpxor RX0, a, RX0; \
362         vpxor RY0, b, RY0; \
363         \
364         vpbroadcastd 4*6(RW), RT0; \
365         vpxor RT0, c, a; \
366         vpbroadcastd 4*7(RW), RT0; \
367         vpxor RT0, d, b; \
368         \
369         vmovdqa RX0, c; \
370         vmovdqa RY0, d;
371
372 #define outunpack_dec8(a,b,c,d) \
373         vpbroadcastd 4*0(RW), RT0; \
374         vpxor RT0, a, a; \
375         \
376         vpbroadcastd 4*1(RW), RT0; \
377         vpxor RT0, b, b; \
378         \
379         vpbroadcastd 4*2(RW), RT0; \
380         vpxor RT0, c, c; \
381         \
382         vpbroadcastd 4*3(RW), RT0; \
383         vpxor RT0, d, d;
384
385 #define transpose4x4_16(a,b,c,d) \
386         transpose_4x4(a ## 0, b ## 0, c ## 0, d ## 0, RX0, RY0); \
387         transpose_4x4(a ## 1, b ## 1, c ## 1, d ## 1, RX0, RY0);
388
389 #define inpack_enc16(a,b,c,d) \
390         inpack_enc8(a ## 0, b ## 0, c ## 0, d ## 0); \
391         inpack_enc8(a ## 1, b ## 1, c ## 1, d ## 1);
392
393 #define outunpack_enc16(a,b,c,d) \
394         outunpack_enc8(a ## 0, b ## 0, c ## 0, d ## 0); \
395         outunpack_enc8(a ## 1, b ## 1, c ## 1, d ## 1);
396
397 #define inpack_dec16(a,b,c,d) \
398         inpack_dec8(a ## 0, b ## 0, c ## 0, d ## 0); \
399         inpack_dec8(a ## 1, b ## 1, c ## 1, d ## 1);
400
401 #define outunpack_dec16(a,b,c,d) \
402         outunpack_dec8(a ## 0, b ## 0, c ## 0, d ## 0); \
403         outunpack_dec8(a ## 1, b ## 1, c ## 1, d ## 1);
404
405 .align 8
406 ELF(.type __twofish_enc_blk16,@function;)
407 __twofish_enc_blk16:
408         /* input:
409          *      %rdi: ctx, CTX
410          *      RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: sixteen parallel
411          *                                              plaintext blocks
412          * output:
413          *      RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: sixteen parallel
414          *                                              ciphertext blocks
415          */
416         CFI_STARTPROC();
417         init_round_constants();
418
419         transpose4x4_16(RA, RB, RC, RD);
420         inpack_enc16(RA, RB, RC, RD);
421
422         encrypt_cycle_first16(0);
423         encrypt_cycle16(2);
424         encrypt_cycle16(4);
425         encrypt_cycle16(6);
426         encrypt_cycle16(8);
427         encrypt_cycle16(10);
428         encrypt_cycle16(12);
429         encrypt_cycle_last16(14);
430
431         outunpack_enc16(RA, RB, RC, RD);
432         transpose4x4_16(RA, RB, RC, RD);
433
434         ret;
435         CFI_ENDPROC();
436 ELF(.size __twofish_enc_blk16,.-__twofish_enc_blk16;)
437
438 .align 8
439 ELF(.type __twofish_dec_blk16,@function;)
440 __twofish_dec_blk16:
441         /* input:
442          *      %rdi: ctx, CTX
443          *      RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: sixteen parallel
444          *                                              plaintext blocks
445          * output:
446          *      RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: sixteen parallel
447          *                                              ciphertext blocks
448          */
449         CFI_STARTPROC();
450         init_round_constants();
451
452         transpose4x4_16(RA, RB, RC, RD);
453         inpack_dec16(RA, RB, RC, RD);
454
455         decrypt_cycle_first16(14);
456         decrypt_cycle16(12);
457         decrypt_cycle16(10);
458         decrypt_cycle16(8);
459         decrypt_cycle16(6);
460         decrypt_cycle16(4);
461         decrypt_cycle16(2);
462         decrypt_cycle_last16(0);
463
464         outunpack_dec16(RA, RB, RC, RD);
465         transpose4x4_16(RA, RB, RC, RD);
466
467         ret;
468         CFI_ENDPROC();
469 ELF(.size __twofish_dec_blk16,.-__twofish_dec_blk16;)
470
471 #define inc_le128(x, minus_one, tmp) \
472         vpcmpeqq minus_one, x, tmp; \
473         vpsubq minus_one, x, x; \
474         vpslldq $8, tmp, tmp; \
475         vpsubq tmp, x, x;
476
477 .align 8
478 .globl _gcry_twofish_avx2_ctr_enc
479 ELF(.type   _gcry_twofish_avx2_ctr_enc,@function;)
480 _gcry_twofish_avx2_ctr_enc:
481         /* input:
482          *      %rdi: ctx, CTX
483          *      %rsi: dst (16 blocks)
484          *      %rdx: src (16 blocks)
485          *      %rcx: iv (big endian, 128bit)
486          */
487         CFI_STARTPROC();
488
489         movq 8(%rcx), %rax;
490         bswapq %rax;
491
492         vzeroupper;
493
494         vbroadcasti128 .Lbswap128_mask rRIP, RTMP3;
495         vpcmpeqd RNOT, RNOT, RNOT;
496         vpsrldq $8, RNOT, RNOT;   /* ab: -1:0 ; cd: -1:0 */
497         vpaddq RNOT, RNOT, RTMP2; /* ab: -2:0 ; cd: -2:0 */
498
499         /* load IV and byteswap */
500         vmovdqu (%rcx), RTMP4x;
501         vpshufb RTMP3x, RTMP4x, RTMP4x;
502         vmovdqa RTMP4x, RTMP0x;
503         inc_le128(RTMP4x, RNOTx, RTMP1x);
504         vinserti128 $1, RTMP4x, RTMP0, RTMP0;
505         vpshufb RTMP3, RTMP0, RA0; /* +1 ; +0 */
506
507         /* check need for handling 64-bit overflow and carry */
508         cmpq $(0xffffffffffffffff - 16), %rax;
509         ja .Lhandle_ctr_carry;
510
511         /* construct IVs */
512         vpsubq RTMP2, RTMP0, RTMP0; /* +3 ; +2 */
513         vpshufb RTMP3, RTMP0, RB0;
514         vpsubq RTMP2, RTMP0, RTMP0; /* +5 ; +4 */
515         vpshufb RTMP3, RTMP0, RC0;
516         vpsubq RTMP2, RTMP0, RTMP0; /* +7 ; +6 */
517         vpshufb RTMP3, RTMP0, RD0;
518         vpsubq RTMP2, RTMP0, RTMP0; /* +9 ; +8 */
519         vpshufb RTMP3, RTMP0, RA1;
520         vpsubq RTMP2, RTMP0, RTMP0; /* +11 ; +10 */
521         vpshufb RTMP3, RTMP0, RB1;
522         vpsubq RTMP2, RTMP0, RTMP0; /* +13 ; +12 */
523         vpshufb RTMP3, RTMP0, RC1;
524         vpsubq RTMP2, RTMP0, RTMP0; /* +15 ; +14 */
525         vpshufb RTMP3, RTMP0, RD1;
526         vpsubq RTMP2, RTMP0, RTMP0; /* +16 */
527         vpshufb RTMP3x, RTMP0x, RTMP0x;
528
529         jmp .Lctr_carry_done;
530
531 .Lhandle_ctr_carry:
532         /* construct IVs */
533         inc_le128(RTMP0, RNOT, RTMP1);
534         inc_le128(RTMP0, RNOT, RTMP1);
535         vpshufb RTMP3, RTMP0, RB0; /* +3 ; +2 */
536         inc_le128(RTMP0, RNOT, RTMP1);
537         inc_le128(RTMP0, RNOT, RTMP1);
538         vpshufb RTMP3, RTMP0, RC0; /* +5 ; +4 */
539         inc_le128(RTMP0, RNOT, RTMP1);
540         inc_le128(RTMP0, RNOT, RTMP1);
541         vpshufb RTMP3, RTMP0, RD0; /* +7 ; +6 */
542         inc_le128(RTMP0, RNOT, RTMP1);
543         inc_le128(RTMP0, RNOT, RTMP1);
544         vpshufb RTMP3, RTMP0, RA1; /* +9 ; +8 */
545         inc_le128(RTMP0, RNOT, RTMP1);
546         inc_le128(RTMP0, RNOT, RTMP1);
547         vpshufb RTMP3, RTMP0, RB1; /* +11 ; +10 */
548         inc_le128(RTMP0, RNOT, RTMP1);
549         inc_le128(RTMP0, RNOT, RTMP1);
550         vpshufb RTMP3, RTMP0, RC1; /* +13 ; +12 */
551         inc_le128(RTMP0, RNOT, RTMP1);
552         inc_le128(RTMP0, RNOT, RTMP1);
553         vpshufb RTMP3, RTMP0, RD1; /* +15 ; +14 */
554         inc_le128(RTMP0, RNOT, RTMP1);
555         vextracti128 $1, RTMP0, RTMP0x;
556         vpshufb RTMP3x, RTMP0x, RTMP0x; /* +16 */
557
558 .align 4
559 .Lctr_carry_done:
560         /* store new IV */
561         vmovdqu RTMP0x, (%rcx);
562
563         call __twofish_enc_blk16;
564
565         vpxor (0 * 32)(%rdx), RA0, RA0;
566         vpxor (1 * 32)(%rdx), RB0, RB0;
567         vpxor (2 * 32)(%rdx), RC0, RC0;
568         vpxor (3 * 32)(%rdx), RD0, RD0;
569         vpxor (4 * 32)(%rdx), RA1, RA1;
570         vpxor (5 * 32)(%rdx), RB1, RB1;
571         vpxor (6 * 32)(%rdx), RC1, RC1;
572         vpxor (7 * 32)(%rdx), RD1, RD1;
573
574         vmovdqu RA0, (0 * 32)(%rsi);
575         vmovdqu RB0, (1 * 32)(%rsi);
576         vmovdqu RC0, (2 * 32)(%rsi);
577         vmovdqu RD0, (3 * 32)(%rsi);
578         vmovdqu RA1, (4 * 32)(%rsi);
579         vmovdqu RB1, (5 * 32)(%rsi);
580         vmovdqu RC1, (6 * 32)(%rsi);
581         vmovdqu RD1, (7 * 32)(%rsi);
582
583         vzeroall;
584
585         ret;
586         CFI_ENDPROC();
587 ELF(.size _gcry_twofish_avx2_ctr_enc,.-_gcry_twofish_avx2_ctr_enc;)
588
589 .align 8
590 .globl _gcry_twofish_avx2_cbc_dec
591 ELF(.type   _gcry_twofish_avx2_cbc_dec,@function;)
592 _gcry_twofish_avx2_cbc_dec:
593         /* input:
594          *      %rdi: ctx, CTX
595          *      %rsi: dst (16 blocks)
596          *      %rdx: src (16 blocks)
597          *      %rcx: iv
598          */
599         CFI_STARTPROC();
600
601         vzeroupper;
602
603         vmovdqu (0 * 32)(%rdx), RA0;
604         vmovdqu (1 * 32)(%rdx), RB0;
605         vmovdqu (2 * 32)(%rdx), RC0;
606         vmovdqu (3 * 32)(%rdx), RD0;
607         vmovdqu (4 * 32)(%rdx), RA1;
608         vmovdqu (5 * 32)(%rdx), RB1;
609         vmovdqu (6 * 32)(%rdx), RC1;
610         vmovdqu (7 * 32)(%rdx), RD1;
611
612         call __twofish_dec_blk16;
613
614         vmovdqu (%rcx), RNOTx;
615         vinserti128 $1, (%rdx), RNOT, RNOT;
616         vpxor RNOT, RA0, RA0;
617         vpxor (0 * 32 + 16)(%rdx), RB0, RB0;
618         vpxor (1 * 32 + 16)(%rdx), RC0, RC0;
619         vpxor (2 * 32 + 16)(%rdx), RD0, RD0;
620         vpxor (3 * 32 + 16)(%rdx), RA1, RA1;
621         vpxor (4 * 32 + 16)(%rdx), RB1, RB1;
622         vpxor (5 * 32 + 16)(%rdx), RC1, RC1;
623         vpxor (6 * 32 + 16)(%rdx), RD1, RD1;
624         vmovdqu (7 * 32 + 16)(%rdx), RNOTx;
625         vmovdqu RNOTx, (%rcx); /* store new IV */
626
627         vmovdqu RA0, (0 * 32)(%rsi);
628         vmovdqu RB0, (1 * 32)(%rsi);
629         vmovdqu RC0, (2 * 32)(%rsi);
630         vmovdqu RD0, (3 * 32)(%rsi);
631         vmovdqu RA1, (4 * 32)(%rsi);
632         vmovdqu RB1, (5 * 32)(%rsi);
633         vmovdqu RC1, (6 * 32)(%rsi);
634         vmovdqu RD1, (7 * 32)(%rsi);
635
636         vzeroall;
637
638         ret;
639         CFI_ENDPROC();
640 ELF(.size _gcry_twofish_avx2_cbc_dec,.-_gcry_twofish_avx2_cbc_dec;)
641
642 .align 8
643 .globl _gcry_twofish_avx2_cfb_dec
644 ELF(.type   _gcry_twofish_avx2_cfb_dec,@function;)
645 _gcry_twofish_avx2_cfb_dec:
646         /* input:
647          *      %rdi: ctx, CTX
648          *      %rsi: dst (16 blocks)
649          *      %rdx: src (16 blocks)
650          *      %rcx: iv
651          */
652         CFI_STARTPROC();
653
654         vzeroupper;
655
656         /* Load input */
657         vmovdqu (%rcx), RNOTx;
658         vinserti128 $1, (%rdx), RNOT, RA0;
659         vmovdqu (0 * 32 + 16)(%rdx), RB0;
660         vmovdqu (1 * 32 + 16)(%rdx), RC0;
661         vmovdqu (2 * 32 + 16)(%rdx), RD0;
662         vmovdqu (3 * 32 + 16)(%rdx), RA1;
663         vmovdqu (4 * 32 + 16)(%rdx), RB1;
664         vmovdqu (5 * 32 + 16)(%rdx), RC1;
665         vmovdqu (6 * 32 + 16)(%rdx), RD1;
666
667         /* Update IV */
668         vmovdqu (7 * 32 + 16)(%rdx), RNOTx;
669         vmovdqu RNOTx, (%rcx);
670
671         call __twofish_enc_blk16;
672
673         vpxor (0 * 32)(%rdx), RA0, RA0;
674         vpxor (1 * 32)(%rdx), RB0, RB0;
675         vpxor (2 * 32)(%rdx), RC0, RC0;
676         vpxor (3 * 32)(%rdx), RD0, RD0;
677         vpxor (4 * 32)(%rdx), RA1, RA1;
678         vpxor (5 * 32)(%rdx), RB1, RB1;
679         vpxor (6 * 32)(%rdx), RC1, RC1;
680         vpxor (7 * 32)(%rdx), RD1, RD1;
681
682         vmovdqu RA0, (0 * 32)(%rsi);
683         vmovdqu RB0, (1 * 32)(%rsi);
684         vmovdqu RC0, (2 * 32)(%rsi);
685         vmovdqu RD0, (3 * 32)(%rsi);
686         vmovdqu RA1, (4 * 32)(%rsi);
687         vmovdqu RB1, (5 * 32)(%rsi);
688         vmovdqu RC1, (6 * 32)(%rsi);
689         vmovdqu RD1, (7 * 32)(%rsi);
690
691         vzeroall;
692
693         ret;
694         CFI_ENDPROC();
695 ELF(.size _gcry_twofish_avx2_cfb_dec,.-_gcry_twofish_avx2_cfb_dec;)
696
697 .align 8
698 .globl _gcry_twofish_avx2_ocb_enc
699 ELF(.type _gcry_twofish_avx2_ocb_enc,@function;)
700
701 _gcry_twofish_avx2_ocb_enc:
702         /* input:
703          *      %rdi: ctx, CTX
704          *      %rsi: dst (16 blocks)
705          *      %rdx: src (16 blocks)
706          *      %rcx: offset
707          *      %r8 : checksum
708          *      %r9 : L pointers (void *L[16])
709          */
710         CFI_STARTPROC();
711
712         vzeroupper;
713
714         subq $(4 * 8), %rsp;
715         CFI_ADJUST_CFA_OFFSET(4 * 8);
716
717         movq %r10, (0 * 8)(%rsp);
718         movq %r11, (1 * 8)(%rsp);
719         movq %r12, (2 * 8)(%rsp);
720         movq %r13, (3 * 8)(%rsp);
721         CFI_REL_OFFSET(%r10, 0 * 8);
722         CFI_REL_OFFSET(%r11, 1 * 8);
723         CFI_REL_OFFSET(%r12, 2 * 8);
724         CFI_REL_OFFSET(%r13, 3 * 8);
725
726         vmovdqu (%rcx), RTMP0x;
727         vmovdqu (%r8), RTMP1x;
728
729         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
730         /* Checksum_i = Checksum_{i-1} xor P_i  */
731         /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
732
733 #define OCB_INPUT(n, l0reg, l1reg, yreg) \
734           vmovdqu (n * 32)(%rdx), yreg; \
735           vpxor (l0reg), RTMP0x, RNOTx; \
736           vpxor (l1reg), RNOTx, RTMP0x; \
737           vinserti128 $1, RTMP0x, RNOT, RNOT; \
738           vpxor yreg, RTMP1, RTMP1; \
739           vpxor yreg, RNOT, yreg; \
740           vmovdqu RNOT, (n * 32)(%rsi);
741
742         movq (0 * 8)(%r9), %r10;
743         movq (1 * 8)(%r9), %r11;
744         movq (2 * 8)(%r9), %r12;
745         movq (3 * 8)(%r9), %r13;
746         OCB_INPUT(0, %r10, %r11, RA0);
747         OCB_INPUT(1, %r12, %r13, RB0);
748         movq (4 * 8)(%r9), %r10;
749         movq (5 * 8)(%r9), %r11;
750         movq (6 * 8)(%r9), %r12;
751         movq (7 * 8)(%r9), %r13;
752         OCB_INPUT(2, %r10, %r11, RC0);
753         OCB_INPUT(3, %r12, %r13, RD0);
754         movq (8 * 8)(%r9), %r10;
755         movq (9 * 8)(%r9), %r11;
756         movq (10 * 8)(%r9), %r12;
757         movq (11 * 8)(%r9), %r13;
758         OCB_INPUT(4, %r10, %r11, RA1);
759         OCB_INPUT(5, %r12, %r13, RB1);
760         movq (12 * 8)(%r9), %r10;
761         movq (13 * 8)(%r9), %r11;
762         movq (14 * 8)(%r9), %r12;
763         movq (15 * 8)(%r9), %r13;
764         OCB_INPUT(6, %r10, %r11, RC1);
765         OCB_INPUT(7, %r12, %r13, RD1);
766 #undef OCB_INPUT
767
768         vextracti128 $1, RTMP1, RNOTx;
769         vmovdqu RTMP0x, (%rcx);
770         vpxor RNOTx, RTMP1x, RTMP1x;
771         vmovdqu RTMP1x, (%r8);
772
773         movq (0 * 8)(%rsp), %r10;
774         movq (1 * 8)(%rsp), %r11;
775         movq (2 * 8)(%rsp), %r12;
776         movq (3 * 8)(%rsp), %r13;
777         CFI_RESTORE(%r10);
778         CFI_RESTORE(%r11);
779         CFI_RESTORE(%r12);
780         CFI_RESTORE(%r13);
781
782         call __twofish_enc_blk16;
783
784         addq $(4 * 8), %rsp;
785         CFI_ADJUST_CFA_OFFSET(-4 * 8);
786
787         vpxor (0 * 32)(%rsi), RA0, RA0;
788         vpxor (1 * 32)(%rsi), RB0, RB0;
789         vpxor (2 * 32)(%rsi), RC0, RC0;
790         vpxor (3 * 32)(%rsi), RD0, RD0;
791         vpxor (4 * 32)(%rsi), RA1, RA1;
792         vpxor (5 * 32)(%rsi), RB1, RB1;
793         vpxor (6 * 32)(%rsi), RC1, RC1;
794         vpxor (7 * 32)(%rsi), RD1, RD1;
795
796         vmovdqu RA0, (0 * 32)(%rsi);
797         vmovdqu RB0, (1 * 32)(%rsi);
798         vmovdqu RC0, (2 * 32)(%rsi);
799         vmovdqu RD0, (3 * 32)(%rsi);
800         vmovdqu RA1, (4 * 32)(%rsi);
801         vmovdqu RB1, (5 * 32)(%rsi);
802         vmovdqu RC1, (6 * 32)(%rsi);
803         vmovdqu RD1, (7 * 32)(%rsi);
804
805         vzeroall;
806
807         ret;
808         CFI_ENDPROC();
809 ELF(.size _gcry_twofish_avx2_ocb_enc,.-_gcry_twofish_avx2_ocb_enc;)
810
811 .align 8
812 .globl _gcry_twofish_avx2_ocb_dec
813 ELF(.type _gcry_twofish_avx2_ocb_dec,@function;)
814
815 _gcry_twofish_avx2_ocb_dec:
816         /* input:
817          *      %rdi: ctx, CTX
818          *      %rsi: dst (16 blocks)
819          *      %rdx: src (16 blocks)
820          *      %rcx: offset
821          *      %r8 : checksum
822          *      %r9 : L pointers (void *L[16])
823          */
824         CFI_STARTPROC();
825
826         vzeroupper;
827
828         subq $(4 * 8), %rsp;
829         CFI_ADJUST_CFA_OFFSET(4 * 8);
830
831         movq %r10, (0 * 8)(%rsp);
832         movq %r11, (1 * 8)(%rsp);
833         movq %r12, (2 * 8)(%rsp);
834         movq %r13, (3 * 8)(%rsp);
835         CFI_REL_OFFSET(%r10, 0 * 8);
836         CFI_REL_OFFSET(%r11, 1 * 8);
837         CFI_REL_OFFSET(%r12, 2 * 8);
838         CFI_REL_OFFSET(%r13, 3 * 8);
839
840         vmovdqu (%rcx), RTMP0x;
841
842         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
843         /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
844
845 #define OCB_INPUT(n, l0reg, l1reg, yreg) \
846           vmovdqu (n * 32)(%rdx), yreg; \
847           vpxor (l0reg), RTMP0x, RNOTx; \
848           vpxor (l1reg), RNOTx, RTMP0x; \
849           vinserti128 $1, RTMP0x, RNOT, RNOT; \
850           vpxor yreg, RNOT, yreg; \
851           vmovdqu RNOT, (n * 32)(%rsi);
852
853         movq (0 * 8)(%r9), %r10;
854         movq (1 * 8)(%r9), %r11;
855         movq (2 * 8)(%r9), %r12;
856         movq (3 * 8)(%r9), %r13;
857         OCB_INPUT(0, %r10, %r11, RA0);
858         OCB_INPUT(1, %r12, %r13, RB0);
859         movq (4 * 8)(%r9), %r10;
860         movq (5 * 8)(%r9), %r11;
861         movq (6 * 8)(%r9), %r12;
862         movq (7 * 8)(%r9), %r13;
863         OCB_INPUT(2, %r10, %r11, RC0);
864         OCB_INPUT(3, %r12, %r13, RD0);
865         movq (8 * 8)(%r9), %r10;
866         movq (9 * 8)(%r9), %r11;
867         movq (10 * 8)(%r9), %r12;
868         movq (11 * 8)(%r9), %r13;
869         OCB_INPUT(4, %r10, %r11, RA1);
870         OCB_INPUT(5, %r12, %r13, RB1);
871         movq (12 * 8)(%r9), %r10;
872         movq (13 * 8)(%r9), %r11;
873         movq (14 * 8)(%r9), %r12;
874         movq (15 * 8)(%r9), %r13;
875         OCB_INPUT(6, %r10, %r11, RC1);
876         OCB_INPUT(7, %r12, %r13, RD1);
877 #undef OCB_INPUT
878
879         vmovdqu RTMP0x, (%rcx);
880         mov %r8, %rcx
881
882         movq (0 * 8)(%rsp), %r10;
883         movq (1 * 8)(%rsp), %r11;
884         movq (2 * 8)(%rsp), %r12;
885         movq (3 * 8)(%rsp), %r13;
886         CFI_RESTORE(%r10);
887         CFI_RESTORE(%r11);
888         CFI_RESTORE(%r12);
889         CFI_RESTORE(%r13);
890
891         call __twofish_dec_blk16;
892
893         vmovdqu (%rcx), RTMP1x;
894
895         vpxor (0 * 32)(%rsi), RA0, RA0;
896         vpxor (1 * 32)(%rsi), RB0, RB0;
897         vpxor (2 * 32)(%rsi), RC0, RC0;
898         vpxor (3 * 32)(%rsi), RD0, RD0;
899         vpxor (4 * 32)(%rsi), RA1, RA1;
900         vpxor (5 * 32)(%rsi), RB1, RB1;
901         vpxor (6 * 32)(%rsi), RC1, RC1;
902         vpxor (7 * 32)(%rsi), RD1, RD1;
903
904         addq $(4 * 8), %rsp;
905         CFI_ADJUST_CFA_OFFSET(-4 * 8);
906
907         /* Checksum_i = Checksum_{i-1} xor P_i  */
908
909         vmovdqu RA0, (0 * 32)(%rsi);
910         vpxor RA0, RTMP1, RTMP1;
911         vmovdqu RB0, (1 * 32)(%rsi);
912         vpxor RB0, RTMP1, RTMP1;
913         vmovdqu RC0, (2 * 32)(%rsi);
914         vpxor RC0, RTMP1, RTMP1;
915         vmovdqu RD0, (3 * 32)(%rsi);
916         vpxor RD0, RTMP1, RTMP1;
917         vmovdqu RA1, (4 * 32)(%rsi);
918         vpxor RA1, RTMP1, RTMP1;
919         vmovdqu RB1, (5 * 32)(%rsi);
920         vpxor RB1, RTMP1, RTMP1;
921         vmovdqu RC1, (6 * 32)(%rsi);
922         vpxor RC1, RTMP1, RTMP1;
923         vmovdqu RD1, (7 * 32)(%rsi);
924         vpxor RD1, RTMP1, RTMP1;
925
926         vextracti128 $1, RTMP1, RNOTx;
927         vpxor RNOTx, RTMP1x, RTMP1x;
928         vmovdqu RTMP1x, (%rcx);
929
930         vzeroall;
931
932         ret;
933         CFI_ENDPROC();
934 ELF(.size _gcry_twofish_avx2_ocb_dec,.-_gcry_twofish_avx2_ocb_dec;)
935
936 .align 8
937 .globl _gcry_twofish_avx2_ocb_auth
938 ELF(.type _gcry_twofish_avx2_ocb_auth,@function;)
939
940 _gcry_twofish_avx2_ocb_auth:
941         /* input:
942          *      %rdi: ctx, CTX
943          *      %rsi: abuf (16 blocks)
944          *      %rdx: offset
945          *      %rcx: checksum
946          *      %r8 : L pointers (void *L[16])
947          */
948         CFI_STARTPROC();
949
950         vzeroupper;
951
952         subq $(4 * 8), %rsp;
953         CFI_ADJUST_CFA_OFFSET(4 * 8);
954
955         movq %r10, (0 * 8)(%rsp);
956         movq %r11, (1 * 8)(%rsp);
957         movq %r12, (2 * 8)(%rsp);
958         movq %r13, (3 * 8)(%rsp);
959         CFI_REL_OFFSET(%r10, 0 * 8);
960         CFI_REL_OFFSET(%r11, 1 * 8);
961         CFI_REL_OFFSET(%r12, 2 * 8);
962         CFI_REL_OFFSET(%r13, 3 * 8);
963
964         vmovdqu (%rdx), RTMP0x;
965
966         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
967         /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
968
969 #define OCB_INPUT(n, l0reg, l1reg, yreg) \
970           vmovdqu (n * 32)(%rsi), yreg; \
971           vpxor (l0reg), RTMP0x, RNOTx; \
972           vpxor (l1reg), RNOTx, RTMP0x; \
973           vinserti128 $1, RTMP0x, RNOT, RNOT; \
974           vpxor yreg, RNOT, yreg;
975
976         movq (0 * 8)(%r8), %r10;
977         movq (1 * 8)(%r8), %r11;
978         movq (2 * 8)(%r8), %r12;
979         movq (3 * 8)(%r8), %r13;
980         OCB_INPUT(0, %r10, %r11, RA0);
981         OCB_INPUT(1, %r12, %r13, RB0);
982         movq (4 * 8)(%r8), %r10;
983         movq (5 * 8)(%r8), %r11;
984         movq (6 * 8)(%r8), %r12;
985         movq (7 * 8)(%r8), %r13;
986         OCB_INPUT(2, %r10, %r11, RC0);
987         OCB_INPUT(3, %r12, %r13, RD0);
988         movq (8 * 8)(%r8), %r10;
989         movq (9 * 8)(%r8), %r11;
990         movq (10 * 8)(%r8), %r12;
991         movq (11 * 8)(%r8), %r13;
992         OCB_INPUT(4, %r10, %r11, RA1);
993         OCB_INPUT(5, %r12, %r13, RB1);
994         movq (12 * 8)(%r8), %r10;
995         movq (13 * 8)(%r8), %r11;
996         movq (14 * 8)(%r8), %r12;
997         movq (15 * 8)(%r8), %r13;
998         OCB_INPUT(6, %r10, %r11, RC1);
999         OCB_INPUT(7, %r12, %r13, RD1);
1000 #undef OCB_INPUT
1001
1002         vmovdqu RTMP0x, (%rdx);
1003
1004         movq (0 * 8)(%rsp), %r10;
1005         movq (1 * 8)(%rsp), %r11;
1006         movq (2 * 8)(%rsp), %r12;
1007         movq (3 * 8)(%rsp), %r13;
1008         CFI_RESTORE(%r10);
1009         CFI_RESTORE(%r11);
1010         CFI_RESTORE(%r12);
1011         CFI_RESTORE(%r13);
1012
1013         call __twofish_enc_blk16;
1014
1015         vpxor RA0, RB0, RA0;
1016         vpxor RC0, RD0, RC0;
1017         vpxor RA1, RB1, RA1;
1018         vpxor RC1, RD1, RC1;
1019
1020         vpxor RA0, RC0, RA0;
1021         vpxor RA1, RC1, RA1;
1022
1023         addq $(4 * 8), %rsp;
1024         CFI_ADJUST_CFA_OFFSET(-4 * 8);
1025
1026         vpxor RA1, RA0, RTMP1;
1027
1028         vextracti128 $1, RTMP1, RNOTx;
1029         vpxor (%rcx), RTMP1x, RTMP1x;
1030         vpxor RNOTx, RTMP1x, RTMP1x;
1031         vmovdqu RTMP1x, (%rcx);
1032
1033         vzeroall;
1034
1035         ret;
1036         CFI_ENDPROC();
1037 ELF(.size _gcry_twofish_avx2_ocb_auth,.-_gcry_twofish_avx2_ocb_auth;)
1038
1039 .align 16
1040
1041 /* For CTR-mode IV byteswap */
1042  _gcry_twofish_bswap128_mask:
1043 .Lbswap128_mask:
1044         .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
1045 ELF(.size _gcry_twofish_bswap128_mask,.-_gcry_twofish_bswap128_mask;)
1046
1047 #endif /*defined(USE_TWOFISH) && defined(ENABLE_AVX2_SUPPORT)*/
1048 #endif /*__x86_64*/