c726e7bafea3e05fc496dfad33a741b2c4b718e6
[libgcrypt.git] / cipher / serpent-avx2-amd64.S
1 /* serpent-avx2-amd64.S  -  AVX2 implementation of Serpent cipher
2  *
3  * Copyright © 2013 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) && defined(USE_SERPENT) && \
24     defined(ENABLE_AVX2_SUPPORT)
25
26 #ifdef __PIC__
27 #  define RIP (%rip)
28 #else
29 #  define RIP
30 #endif
31
32 /* struct serpent_context: */
33 #define ctx_keys 0
34
35 /* register macros */
36 #define CTX %rdi
37
38 /* vector registers */
39 .set RA0, %ymm0
40 .set RA1, %ymm1
41 .set RA2, %ymm2
42 .set RA3, %ymm3
43 .set RA4, %ymm4
44
45 .set RB0, %ymm5
46 .set RB1, %ymm6
47 .set RB2, %ymm7
48 .set RB3, %ymm8
49 .set RB4, %ymm9
50
51 .set RNOT, %ymm10
52 .set RTMP0, %ymm11
53 .set RTMP1, %ymm12
54 .set RTMP2, %ymm13
55 .set RTMP3, %ymm14
56 .set RTMP4, %ymm15
57
58 .set RNOTx, %xmm10
59 .set RTMP0x, %xmm11
60 .set RTMP1x, %xmm12
61 .set RTMP2x, %xmm13
62 .set RTMP3x, %xmm14
63 .set RTMP4x, %xmm15
64
65 /**********************************************************************
66   helper macros
67  **********************************************************************/
68
69 /* preprocessor macro for renaming vector registers using GAS macros */
70 #define sbox_reg_rename(r0, r1, r2, r3, r4, \
71                         new_r0, new_r1, new_r2, new_r3, new_r4) \
72         .set rename_reg0, new_r0; \
73         .set rename_reg1, new_r1; \
74         .set rename_reg2, new_r2; \
75         .set rename_reg3, new_r3; \
76         .set rename_reg4, new_r4; \
77         \
78         .set r0, rename_reg0; \
79         .set r1, rename_reg1; \
80         .set r2, rename_reg2; \
81         .set r3, rename_reg3; \
82         .set r4, rename_reg4;
83
84 /* vector 32-bit rotation to left */
85 #define vec_rol(reg, nleft, tmp) \
86         vpslld $(nleft), reg, tmp;              \
87         vpsrld $(32 - (nleft)), reg, reg;       \
88         vpor tmp, reg, reg;
89
90 /* vector 32-bit rotation to right */
91 #define vec_ror(reg, nright, tmp) \
92         vec_rol(reg, 32 - nright, tmp)
93
94 /* 4x4 32-bit integer matrix transpose */
95 #define transpose_4x4(x0, x1, x2, x3, t1, t2, t3) \
96         vpunpckhdq x1, x0, t2; \
97         vpunpckldq x1, x0, x0; \
98         \
99         vpunpckldq x3, x2, t1; \
100         vpunpckhdq x3, x2, x2; \
101         \
102         vpunpckhqdq t1, x0, x1; \
103         vpunpcklqdq t1, x0, x0; \
104         \
105         vpunpckhqdq x2, t2, x3; \
106         vpunpcklqdq x2, t2, x2;
107
108 /**********************************************************************
109   16-way serpent
110  **********************************************************************/
111
112 /*
113  * These are the S-Boxes of Serpent from following research paper.
114  *
115  *  D. A. Osvik, “Speeding up Serpent,” in Third AES Candidate Conference,
116  *   (New York, New York, USA), p. 317–329, National Institute of Standards and
117  *   Technology, 2000.
118  *
119  * Paper is also available at: http://www.ii.uib.no/~osvik/pub/aes3.pdf
120  *
121  */
122 #define SBOX0(r0, r1, r2, r3, r4) \
123         vpxor   r0, r3, r3;             vmovdqa r1, r4;                 \
124         vpand   r3, r1, r1;             vpxor   r2, r4, r4;             \
125         vpxor   r0, r1, r1;             vpor    r3, r0, r0;             \
126         vpxor   r4, r0, r0;             vpxor   r3, r4, r4;             \
127         vpxor   r2, r3, r3;             vpor    r1, r2, r2;             \
128         vpxor   r4, r2, r2;             vpxor   RNOT, r4, r4;           \
129         vpor    r1, r4, r4;             vpxor   r3, r1, r1;             \
130         vpxor   r4, r1, r1;             vpor    r0, r3, r3;             \
131         vpxor   r3, r1, r1;             vpxor   r3, r4, r4;             \
132         \
133         sbox_reg_rename(r0,r1,r2,r3,r4, r1,r4,r2,r0,r3);
134
135 #define SBOX0_INVERSE(r0, r1, r2, r3, r4) \
136         vpxor   RNOT, r2, r2;           vmovdqa r1, r4;                 \
137         vpor    r0, r1, r1;             vpxor   RNOT, r4, r4;           \
138         vpxor   r2, r1, r1;             vpor    r4, r2, r2;             \
139         vpxor   r3, r1, r1;             vpxor   r4, r0, r0;             \
140         vpxor   r0, r2, r2;             vpand   r3, r0, r0;             \
141         vpxor   r0, r4, r4;             vpor    r1, r0, r0;             \
142         vpxor   r2, r0, r0;             vpxor   r4, r3, r3;             \
143         vpxor   r1, r2, r2;             vpxor   r0, r3, r3;             \
144         vpxor   r1, r3, r3;     \
145         vpand   r3, r2, r2;     \
146         vpxor   r2, r4, r4;     \
147         \
148         sbox_reg_rename(r0,r1,r2,r3,r4, r0,r4,r1,r3,r2);
149
150 #define SBOX1(r0, r1, r2, r3, r4) \
151         vpxor   RNOT, r0, r0;           vpxor   RNOT, r2, r2;           \
152         vmovdqa r0, r4;                 vpand   r1, r0, r0;             \
153         vpxor   r0, r2, r2;             vpor    r3, r0, r0;             \
154         vpxor   r2, r3, r3;             vpxor   r0, r1, r1;             \
155         vpxor   r4, r0, r0;             vpor    r1, r4, r4;             \
156         vpxor   r3, r1, r1;             vpor    r0, r2, r2;             \
157         vpand   r4, r2, r2;             vpxor   r1, r0, r0;             \
158         vpand   r2, r1, r1;     \
159         vpxor   r0, r1, r1;             vpand   r2, r0, r0;             \
160         vpxor   r4, r0, r0;     \
161         \
162         sbox_reg_rename(r0,r1,r2,r3,r4, r2,r0,r3,r1,r4);
163
164 #define SBOX1_INVERSE(r0, r1, r2, r3, r4) \
165         vmovdqa r1, r4;                 vpxor   r3, r1, r1;             \
166         vpand   r1, r3, r3;             vpxor   r2, r4, r4;             \
167         vpxor   r0, r3, r3;             vpor    r1, r0, r0;             \
168         vpxor   r3, r2, r2;             vpxor   r4, r0, r0;             \
169         vpor    r2, r0, r0;             vpxor   r3, r1, r1;             \
170         vpxor   r1, r0, r0;             vpor    r3, r1, r1;             \
171         vpxor   r0, r1, r1;             vpxor   RNOT, r4, r4;           \
172         vpxor   r1, r4, r4;             vpor    r0, r1, r1;             \
173         vpxor   r0, r1, r1;     \
174         vpor    r4, r1, r1;     \
175         vpxor   r1, r3, r3;     \
176         \
177         sbox_reg_rename(r0,r1,r2,r3,r4, r4,r0,r3,r2,r1);
178
179 #define SBOX2(r0, r1, r2, r3, r4) \
180         vmovdqa r0, r4;                 vpand   r2, r0, r0;             \
181         vpxor   r3, r0, r0;             vpxor   r1, r2, r2;             \
182         vpxor   r0, r2, r2;             vpor    r4, r3, r3;             \
183         vpxor   r1, r3, r3;             vpxor   r2, r4, r4;             \
184         vmovdqa r3, r1;                 vpor    r4, r3, r3;             \
185         vpxor   r0, r3, r3;             vpand   r1, r0, r0;             \
186         vpxor   r0, r4, r4;             vpxor   r3, r1, r1;             \
187         vpxor   r4, r1, r1;             vpxor   RNOT, r4, r4;           \
188         \
189         sbox_reg_rename(r0,r1,r2,r3,r4, r2,r3,r1,r4,r0);
190
191 #define SBOX2_INVERSE(r0, r1, r2, r3, r4) \
192         vpxor   r3, r2, r2;             vpxor   r0, r3, r3;             \
193         vmovdqa r3, r4;                 vpand   r2, r3, r3;             \
194         vpxor   r1, r3, r3;             vpor    r2, r1, r1;             \
195         vpxor   r4, r1, r1;             vpand   r3, r4, r4;             \
196         vpxor   r3, r2, r2;             vpand   r0, r4, r4;             \
197         vpxor   r2, r4, r4;             vpand   r1, r2, r2;             \
198         vpor    r0, r2, r2;             vpxor   RNOT, r3, r3;           \
199         vpxor   r3, r2, r2;             vpxor   r3, r0, r0;             \
200         vpand   r1, r0, r0;             vpxor   r4, r3, r3;             \
201         vpxor   r0, r3, r3;     \
202         \
203         sbox_reg_rename(r0,r1,r2,r3,r4, r1,r4,r2,r3,r0);
204
205 #define SBOX3(r0, r1, r2, r3, r4) \
206         vmovdqa r0, r4;                 vpor    r3, r0, r0;             \
207         vpxor   r1, r3, r3;             vpand   r4, r1, r1;             \
208         vpxor   r2, r4, r4;             vpxor   r3, r2, r2;             \
209         vpand   r0, r3, r3;             vpor    r1, r4, r4;             \
210         vpxor   r4, r3, r3;             vpxor   r1, r0, r0;             \
211         vpand   r0, r4, r4;             vpxor   r3, r1, r1;             \
212         vpxor   r2, r4, r4;             vpor    r0, r1, r1;             \
213         vpxor   r2, r1, r1;             vpxor   r3, r0, r0;             \
214         vmovdqa r1, r2;                 vpor    r3, r1, r1;             \
215         vpxor   r0, r1, r1;     \
216         \
217         sbox_reg_rename(r0,r1,r2,r3,r4, r1,r2,r3,r4,r0);
218
219 #define SBOX3_INVERSE(r0, r1, r2, r3, r4) \
220         vmovdqa r2, r4;                 vpxor   r1, r2, r2;             \
221         vpxor   r2, r0, r0;             vpand   r2, r4, r4;             \
222         vpxor   r0, r4, r4;             vpand   r1, r0, r0;             \
223         vpxor   r3, r1, r1;             vpor    r4, r3, r3;             \
224         vpxor   r3, r2, r2;             vpxor   r3, r0, r0;             \
225         vpxor   r4, r1, r1;             vpand   r2, r3, r3;             \
226         vpxor   r1, r3, r3;             vpxor   r0, r1, r1;             \
227         vpor    r2, r1, r1;             vpxor   r3, r0, r0;             \
228         vpxor   r4, r1, r1;     \
229         vpxor   r1, r0, r0;     \
230         \
231         sbox_reg_rename(r0,r1,r2,r3,r4, r2,r1,r3,r0,r4);
232
233 #define SBOX4(r0, r1, r2, r3, r4) \
234         vpxor   r3, r1, r1;             vpxor   RNOT, r3, r3;           \
235         vpxor   r3, r2, r2;             vpxor   r0, r3, r3;             \
236         vmovdqa r1, r4;                 vpand   r3, r1, r1;             \
237         vpxor   r2, r1, r1;             vpxor   r3, r4, r4;             \
238         vpxor   r4, r0, r0;             vpand   r4, r2, r2;             \
239         vpxor   r0, r2, r2;             vpand   r1, r0, r0;             \
240         vpxor   r0, r3, r3;             vpor    r1, r4, r4;             \
241         vpxor   r0, r4, r4;             vpor    r3, r0, r0;             \
242         vpxor   r2, r0, r0;             vpand   r3, r2, r2;             \
243         vpxor   RNOT, r0, r0;           vpxor   r2, r4, r4;             \
244         \
245         sbox_reg_rename(r0,r1,r2,r3,r4, r1,r4,r0,r3,r2);
246
247 #define SBOX4_INVERSE(r0, r1, r2, r3, r4) \
248         vmovdqa r2, r4;                 vpand   r3, r2, r2;             \
249         vpxor   r1, r2, r2;             vpor    r3, r1, r1;             \
250         vpand   r0, r1, r1;             vpxor   r2, r4, r4;             \
251         vpxor   r1, r4, r4;             vpand   r2, r1, r1;             \
252         vpxor   RNOT, r0, r0;           vpxor   r4, r3, r3;             \
253         vpxor   r3, r1, r1;             vpand   r0, r3, r3;             \
254         vpxor   r2, r3, r3;             vpxor   r1, r0, r0;             \
255         vpand   r0, r2, r2;             vpxor   r0, r3, r3;             \
256         vpxor   r4, r2, r2;     \
257         vpor    r3, r2, r2;             vpxor   r0, r3, r3;             \
258         vpxor   r1, r2, r2;     \
259         \
260         sbox_reg_rename(r0,r1,r2,r3,r4, r0,r3,r2,r4,r1);
261
262 #define SBOX5(r0, r1, r2, r3, r4) \
263         vpxor   r1, r0, r0;             vpxor   r3, r1, r1;             \
264         vpxor   RNOT, r3, r3;           vmovdqa r1, r4;                 \
265         vpand   r0, r1, r1;             vpxor   r3, r2, r2;             \
266         vpxor   r2, r1, r1;             vpor    r4, r2, r2;             \
267         vpxor   r3, r4, r4;             vpand   r1, r3, r3;             \
268         vpxor   r0, r3, r3;             vpxor   r1, r4, r4;             \
269         vpxor   r2, r4, r4;             vpxor   r0, r2, r2;             \
270         vpand   r3, r0, r0;             vpxor   RNOT, r2, r2;           \
271         vpxor   r4, r0, r0;             vpor    r3, r4, r4;             \
272         vpxor   r4, r2, r2;     \
273         \
274         sbox_reg_rename(r0,r1,r2,r3,r4, r1,r3,r0,r2,r4);
275
276 #define SBOX5_INVERSE(r0, r1, r2, r3, r4) \
277         vpxor   RNOT, r1, r1;           vmovdqa r3, r4;                 \
278         vpxor   r1, r2, r2;             vpor    r0, r3, r3;             \
279         vpxor   r2, r3, r3;             vpor    r1, r2, r2;             \
280         vpand   r0, r2, r2;             vpxor   r3, r4, r4;             \
281         vpxor   r4, r2, r2;             vpor    r0, r4, r4;             \
282         vpxor   r1, r4, r4;             vpand   r2, r1, r1;             \
283         vpxor   r3, r1, r1;             vpxor   r2, r4, r4;             \
284         vpand   r4, r3, r3;             vpxor   r1, r4, r4;             \
285         vpxor   r4, r3, r3;             vpxor   RNOT, r4, r4;           \
286         vpxor   r0, r3, r3;     \
287         \
288         sbox_reg_rename(r0,r1,r2,r3,r4, r1,r4,r3,r2,r0);
289
290 #define SBOX6(r0, r1, r2, r3, r4) \
291         vpxor   RNOT, r2, r2;           vmovdqa r3, r4;                 \
292         vpand   r0, r3, r3;             vpxor   r4, r0, r0;             \
293         vpxor   r2, r3, r3;             vpor    r4, r2, r2;             \
294         vpxor   r3, r1, r1;             vpxor   r0, r2, r2;             \
295         vpor    r1, r0, r0;             vpxor   r1, r2, r2;             \
296         vpxor   r0, r4, r4;             vpor    r3, r0, r0;             \
297         vpxor   r2, r0, r0;             vpxor   r3, r4, r4;             \
298         vpxor   r0, r4, r4;             vpxor   RNOT, r3, r3;           \
299         vpand   r4, r2, r2;     \
300         vpxor   r3, r2, r2;     \
301         \
302         sbox_reg_rename(r0,r1,r2,r3,r4, r0,r1,r4,r2,r3);
303
304 #define SBOX6_INVERSE(r0, r1, r2, r3, r4) \
305         vpxor   r2, r0, r0;             vmovdqa r2, r4;                 \
306         vpand   r0, r2, r2;             vpxor   r3, r4, r4;             \
307         vpxor   RNOT, r2, r2;           vpxor   r1, r3, r3;             \
308         vpxor   r3, r2, r2;             vpor    r0, r4, r4;             \
309         vpxor   r2, r0, r0;             vpxor   r4, r3, r3;             \
310         vpxor   r1, r4, r4;             vpand   r3, r1, r1;             \
311         vpxor   r0, r1, r1;             vpxor   r3, r0, r0;             \
312         vpor    r2, r0, r0;             vpxor   r1, r3, r3;             \
313         vpxor   r0, r4, r4;     \
314         \
315         sbox_reg_rename(r0,r1,r2,r3,r4, r1,r2,r4,r3,r0);
316
317 #define SBOX7(r0, r1, r2, r3, r4) \
318         vmovdqa r1, r4;                 vpor    r2, r1, r1;             \
319         vpxor   r3, r1, r1;             vpxor   r2, r4, r4;             \
320         vpxor   r1, r2, r2;             vpor    r4, r3, r3;             \
321         vpand   r0, r3, r3;             vpxor   r2, r4, r4;             \
322         vpxor   r1, r3, r3;             vpor    r4, r1, r1;             \
323         vpxor   r0, r1, r1;             vpor    r4, r0, r0;             \
324         vpxor   r2, r0, r0;             vpxor   r4, r1, r1;             \
325         vpxor   r1, r2, r2;             vpand   r0, r1, r1;             \
326         vpxor   r4, r1, r1;             vpxor   RNOT, r2, r2;           \
327         vpor    r0, r2, r2;     \
328         vpxor   r2, r4, r4;     \
329         \
330         sbox_reg_rename(r0,r1,r2,r3,r4, r4,r3,r1,r0,r2);
331
332 #define SBOX7_INVERSE(r0, r1, r2, r3, r4) \
333         vmovdqa r2, r4;                 vpxor   r0, r2, r2;             \
334         vpand   r3, r0, r0;             vpor    r3, r4, r4;             \
335         vpxor   RNOT, r2, r2;           vpxor   r1, r3, r3;             \
336         vpor    r0, r1, r1;             vpxor   r2, r0, r0;             \
337         vpand   r4, r2, r2;             vpand   r4, r3, r3;             \
338         vpxor   r2, r1, r1;             vpxor   r0, r2, r2;             \
339         vpor    r2, r0, r0;             vpxor   r1, r4, r4;             \
340         vpxor   r3, r0, r0;             vpxor   r4, r3, r3;             \
341         vpor    r0, r4, r4;             vpxor   r2, r3, r3;             \
342         vpxor   r2, r4, r4;     \
343         \
344         sbox_reg_rename(r0,r1,r2,r3,r4, r3,r0,r1,r4,r2);
345
346 /* Apply SBOX number WHICH to to the block.  */
347 #define SBOX(which, r0, r1, r2, r3, r4) \
348         SBOX##which (r0, r1, r2, r3, r4)
349
350 /* Apply inverse SBOX number WHICH to to the block.  */
351 #define SBOX_INVERSE(which, r0, r1, r2, r3, r4) \
352         SBOX##which##_INVERSE (r0, r1, r2, r3, r4)
353
354 /* XOR round key into block state in r0,r1,r2,r3. r4 used as temporary.  */
355 #define BLOCK_XOR_KEY(r0, r1, r2, r3, r4, round) \
356         vpbroadcastd (ctx_keys + (round) * 16 + 0 * 4)(CTX), r4; \
357         vpxor r4, r0, r0; \
358         vpbroadcastd (ctx_keys + (round) * 16 + 1 * 4)(CTX), r4; \
359         vpxor r4, r1, r1; \
360         vpbroadcastd (ctx_keys + (round) * 16 + 2 * 4)(CTX), r4; \
361         vpxor r4, r2, r2; \
362         vpbroadcastd (ctx_keys + (round) * 16 + 3 * 4)(CTX), r4; \
363         vpxor r4, r3, r3;
364
365 /* Apply the linear transformation to BLOCK.  */
366 #define LINEAR_TRANSFORMATION(r0, r1, r2, r3, r4) \
367         vec_rol(r0, 13, r4);    \
368         vec_rol(r2, 3, r4);     \
369         vpxor r0, r1, r1;       \
370         vpxor r2, r1, r1;       \
371         vpslld $3, r0, r4;      \
372         vpxor r2, r3, r3;       \
373         vpxor r4, r3, r3;       \
374         vec_rol(r1, 1, r4);     \
375         vec_rol(r3, 7, r4);     \
376         vpxor r1, r0, r0;       \
377         vpxor r3, r0, r0;       \
378         vpslld $7, r1, r4;      \
379         vpxor r3, r2, r2;       \
380         vpxor r4, r2, r2;       \
381         vec_rol(r0, 5, r4);     \
382         vec_rol(r2, 22, r4);
383
384 /* Apply the inverse linear transformation to BLOCK.  */
385 #define LINEAR_TRANSFORMATION_INVERSE(r0, r1, r2, r3, r4) \
386         vec_ror(r2, 22, r4);    \
387         vec_ror(r0, 5, r4);     \
388         vpslld $7, r1, r4;      \
389         vpxor r3, r2, r2;       \
390         vpxor r4, r2, r2;       \
391         vpxor r1, r0, r0;       \
392         vpxor r3, r0, r0;       \
393         vec_ror(r3, 7, r4);     \
394         vec_ror(r1, 1, r4);     \
395         vpslld $3, r0, r4;      \
396         vpxor r2, r3, r3;       \
397         vpxor r4, r3, r3;       \
398         vpxor r0, r1, r1;       \
399         vpxor r2, r1, r1;       \
400         vec_ror(r2, 3, r4);     \
401         vec_ror(r0, 13, r4);
402
403 /* Apply a Serpent round to sixteen parallel blocks.  This macro increments
404    `round'.  */
405 #define ROUND(which, a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
406         BLOCK_XOR_KEY (a0, a1, a2, a3, a4, round);      \
407         SBOX (which, a0, a1, a2, a3, a4);               \
408                 BLOCK_XOR_KEY (b0, b1, b2, b3, b4, round);      \
409                 SBOX (which, b0, b1, b2, b3, b4);               \
410         LINEAR_TRANSFORMATION (a0, a1, a2, a3, a4);     \
411                 LINEAR_TRANSFORMATION (b0, b1, b2, b3, b4);     \
412         .set round, (round + 1);
413
414 /* Apply the last Serpent round to sixteen parallel blocks.  This macro
415    increments `round'.  */
416 #define ROUND_LAST(which, a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
417         BLOCK_XOR_KEY (a0, a1, a2, a3, a4, round);      \
418         SBOX (which, a0, a1, a2, a3, a4);               \
419                 BLOCK_XOR_KEY (b0, b1, b2, b3, b4, round);      \
420                 SBOX (which, b0, b1, b2, b3, b4);               \
421         .set round, (round + 1);                        \
422         BLOCK_XOR_KEY (a0, a1, a2, a3, a4, round);      \
423                 BLOCK_XOR_KEY (b0, b1, b2, b3, b4, round);      \
424         .set round, (round + 1);
425
426 /* Apply an inverse Serpent round to sixteen parallel blocks.  This macro
427    increments `round'.  */
428 #define ROUND_INVERSE(which, a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
429         LINEAR_TRANSFORMATION_INVERSE (a0, a1, a2, a3, a4);     \
430                 LINEAR_TRANSFORMATION_INVERSE (b0, b1, b2, b3, b4);     \
431         SBOX_INVERSE (which, a0, a1, a2, a3, a4);               \
432         BLOCK_XOR_KEY (a0, a1, a2, a3, a4, round);              \
433                 SBOX_INVERSE (which, b0, b1, b2, b3, b4);               \
434                 BLOCK_XOR_KEY (b0, b1, b2, b3, b4, round);              \
435         .set round, (round - 1);
436
437 /* Apply the first inverse Serpent round to sixteen parallel blocks.  This macro
438    increments `round'.  */
439 #define ROUND_FIRST_INVERSE(which, a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
440         BLOCK_XOR_KEY (a0, a1, a2, a3, a4, round);      \
441                 BLOCK_XOR_KEY (b0, b1, b2, b3, b4, round);      \
442         .set round, (round - 1);                        \
443         SBOX_INVERSE (which, a0, a1, a2, a3, a4);       \
444         BLOCK_XOR_KEY (a0, a1, a2, a3, a4, round);      \
445                 SBOX_INVERSE (which, b0, b1, b2, b3, b4);       \
446                 BLOCK_XOR_KEY (b0, b1, b2, b3, b4, round);      \
447         .set round, (round - 1);
448
449 .text
450
451 .align 8
452 .type   __serpent_enc_blk16,@function;
453 __serpent_enc_blk16:
454         /* input:
455          *      %rdi: ctx, CTX
456          *      RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: sixteen parallel
457          *                                              plaintext blocks
458          * output:
459          *      RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: sixteen parallel
460          *                                              ciphertext blocks
461          */
462
463         /* record input vector names for __serpent_enc_blk16 */
464         .set enc_in_a0, RA0
465         .set enc_in_a1, RA1
466         .set enc_in_a2, RA2
467         .set enc_in_a3, RA3
468         .set enc_in_b0, RB0
469         .set enc_in_b1, RB1
470         .set enc_in_b2, RB2
471         .set enc_in_b3, RB3
472
473         vpcmpeqd RNOT, RNOT, RNOT;
474
475         transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
476         transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
477
478         .set round, 0
479         ROUND (0, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
480         ROUND (1, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
481         ROUND (2, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
482         ROUND (3, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
483         ROUND (4, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
484         ROUND (5, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
485         ROUND (6, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
486         ROUND (7, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
487         ROUND (0, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
488         ROUND (1, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
489         ROUND (2, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
490         ROUND (3, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
491         ROUND (4, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
492         ROUND (5, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
493         ROUND (6, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
494         ROUND (7, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
495         ROUND (0, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
496         ROUND (1, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
497         ROUND (2, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
498         ROUND (3, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
499         ROUND (4, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
500         ROUND (5, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
501         ROUND (6, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
502         ROUND (7, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
503         ROUND (0, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
504         ROUND (1, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
505         ROUND (2, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
506         ROUND (3, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
507         ROUND (4, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
508         ROUND (5, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
509         ROUND (6, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
510
511         ROUND_LAST (7, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
512
513         transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
514         transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
515
516         /* record output vector names for __serpent_enc_blk16 */
517         .set enc_out_a0, RA0
518         .set enc_out_a1, RA1
519         .set enc_out_a2, RA2
520         .set enc_out_a3, RA3
521         .set enc_out_b0, RB0
522         .set enc_out_b1, RB1
523         .set enc_out_b2, RB2
524         .set enc_out_b3, RB3
525
526         ret;
527 .size __serpent_enc_blk16,.-__serpent_enc_blk16;
528
529 .align 8
530 .type   __serpent_dec_blk16,@function;
531 __serpent_dec_blk16:
532         /* input:
533          *      %rdi: ctx, CTX
534          *      RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: sixteen parallel
535          *                                              ciphertext blocks
536          * output:
537          *      RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: sixteen parallel
538          *                                              plaintext blocks
539          */
540
541         /* record input vector names for __serpent_dec_blk16 */
542         .set dec_in_a0, RA0
543         .set dec_in_a1, RA1
544         .set dec_in_a2, RA2
545         .set dec_in_a3, RA3
546         .set dec_in_b0, RB0
547         .set dec_in_b1, RB1
548         .set dec_in_b2, RB2
549         .set dec_in_b3, RB3
550
551         vpcmpeqd RNOT, RNOT, RNOT;
552
553         transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
554         transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
555
556         .set round, 32
557         ROUND_FIRST_INVERSE (7, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
558
559         ROUND_INVERSE (6, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
560         ROUND_INVERSE (5, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
561         ROUND_INVERSE (4, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
562         ROUND_INVERSE (3, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
563         ROUND_INVERSE (2, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
564         ROUND_INVERSE (1, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
565         ROUND_INVERSE (0, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
566         ROUND_INVERSE (7, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
567         ROUND_INVERSE (6, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
568         ROUND_INVERSE (5, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
569         ROUND_INVERSE (4, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
570         ROUND_INVERSE (3, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
571         ROUND_INVERSE (2, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
572         ROUND_INVERSE (1, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
573         ROUND_INVERSE (0, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
574         ROUND_INVERSE (7, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
575         ROUND_INVERSE (6, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
576         ROUND_INVERSE (5, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
577         ROUND_INVERSE (4, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
578         ROUND_INVERSE (3, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
579         ROUND_INVERSE (2, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
580         ROUND_INVERSE (1, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
581         ROUND_INVERSE (0, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
582         ROUND_INVERSE (7, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
583         ROUND_INVERSE (6, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
584         ROUND_INVERSE (5, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
585         ROUND_INVERSE (4, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
586         ROUND_INVERSE (3, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
587         ROUND_INVERSE (2, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
588         ROUND_INVERSE (1, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
589         ROUND_INVERSE (0, RA0, RA1, RA2, RA3, RA4, RB0, RB1, RB2, RB3, RB4);
590
591         transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
592         transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
593
594         /* record output vector names for __serpent_dec_blk16 */
595         .set dec_out_a0, RA0
596         .set dec_out_a1, RA1
597         .set dec_out_a2, RA2
598         .set dec_out_a3, RA3
599         .set dec_out_b0, RB0
600         .set dec_out_b1, RB1
601         .set dec_out_b2, RB2
602         .set dec_out_b3, RB3
603
604         ret;
605 .size __serpent_dec_blk16,.-__serpent_dec_blk16;
606
607 #define inc_le128(x, minus_one, tmp) \
608         vpcmpeqq minus_one, x, tmp; \
609         vpsubq minus_one, x, x; \
610         vpslldq $8, tmp, tmp; \
611         vpsubq tmp, x, x;
612
613 .align 8
614 .global _gcry_serpent_avx2_ctr_enc
615 .type   _gcry_serpent_avx2_ctr_enc,@function;
616 _gcry_serpent_avx2_ctr_enc:
617         /* input:
618          *      %rdi: ctx, CTX
619          *      %rsi: dst (16 blocks)
620          *      %rdx: src (16 blocks)
621          *      %rcx: iv (big endian, 128bit)
622          */
623
624         vzeroupper;
625
626         .set RA0, enc_in_a0
627         .set RA1, enc_in_a1
628         .set RA2, enc_in_a2
629         .set RA3, enc_in_a3
630         .set RB0, enc_in_b0
631         .set RB1, enc_in_b1
632         .set RB2, enc_in_b2
633         .set RB3, enc_in_b3
634
635         vbroadcasti128 .Lbswap128_mask RIP, RTMP3;
636         vpcmpeqd RNOT, RNOT, RNOT;
637         vpsrldq $8, RNOT, RNOT;   /* ab: -1:0 ; cd: -1:0 */
638         vpaddq RNOT, RNOT, RTMP2; /* ab: -2:0 ; cd: -2:0 */
639
640         /* load IV and byteswap */
641         vmovdqu (%rcx), RTMP4x;
642         vpshufb RTMP3x, RTMP4x, RTMP4x;
643         vmovdqa RTMP4x, RTMP0x;
644         inc_le128(RTMP4x, RNOTx, RTMP1x);
645         vinserti128 $1, RTMP4x, RTMP0, RTMP0;
646         vpshufb RTMP3, RTMP0, RA0; /* +1 ; +0 */
647
648         /* check need for handling 64-bit overflow and carry */
649         cmpq $(0xffffffffffffffff - 16), (%rcx);
650         ja .Lhandle_ctr_carry;
651
652         /* construct IVs */
653         vpsubq RTMP2, RTMP0, RA1; /* +3 ; +2 */
654         vpshufb RTMP3, RA1, RA1;
655         vpsubq RTMP2, RA1, RA2;   /* +5 ; +4 */
656         vpshufb RTMP3, RA2, RA2;
657         vpsubq RTMP2, RA2, RA3;   /* +7 ; +6 */
658         vpshufb RTMP3, RA3, RA3;
659         vpsubq RTMP2, RA3, RB0;   /* +9 ; +8 */
660         vpshufb RTMP3, RB0, RB0;
661         vpsubq RTMP2, RB0, RB1;   /* +11 ; +10 */
662         vpshufb RTMP3, RB1, RB1;
663         vpsubq RTMP2, RB1, RB2;   /* +13 ; +12 */
664         vpshufb RTMP3, RB2, RB2;
665         vpsubq RTMP2, RB2, RB3;   /* +15 ; +14 */
666         vpshufb RTMP3, RB3, RB3;
667         vpsubq RTMP2, RB3, RTMP0; /* +16 */
668         vpshufb RTMP3x, RTMP0x, RTMP0x;
669
670         jmp .Lctr_carry_done;
671
672 .Lhandle_ctr_carry:
673         /* construct IVs */
674         inc_le128(RTMP0, RNOT, RTMP1);
675         inc_le128(RTMP0, RNOT, RTMP1);
676         vpshufb RTMP3, RTMP0, RA1; /* +3 ; +2 */
677         inc_le128(RTMP0, RNOT, RTMP1);
678         inc_le128(RTMP0, RNOT, RTMP1);
679         vpshufb RTMP3, RTMP0, RA2; /* +5 ; +4 */
680         inc_le128(RTMP0, RNOT, RTMP1);
681         inc_le128(RTMP0, RNOT, RTMP1);
682         vpshufb RTMP3, RTMP0, RA3; /* +7 ; +6 */
683         inc_le128(RTMP0, RNOT, RTMP1);
684         inc_le128(RTMP0, RNOT, RTMP1);
685         vpshufb RTMP3, RTMP0, RB0; /* +9 ; +8 */
686         inc_le128(RTMP0, RNOT, RTMP1);
687         inc_le128(RTMP0, RNOT, RTMP1);
688         vpshufb RTMP3, RTMP0, RB1; /* +11 ; +10 */
689         inc_le128(RTMP0, RNOT, RTMP1);
690         inc_le128(RTMP0, RNOT, RTMP1);
691         vpshufb RTMP3, RTMP0, RB2; /* +13 ; +12 */
692         inc_le128(RTMP0, RNOT, RTMP1);
693         inc_le128(RTMP0, RNOT, RTMP1);
694         vpshufb RTMP3, RTMP0, RB3; /* +15 ; +14 */
695         inc_le128(RTMP0, RNOT, RTMP1);
696         vextracti128 $1, RTMP0, RTMP0x;
697         vpshufb RTMP3x, RTMP0x, RTMP0x; /* +16 */
698
699 .align 4
700 .Lctr_carry_done:
701         /* store new IV */
702         vmovdqu RTMP0x, (%rcx);
703
704         call __serpent_enc_blk16;
705
706         .set RA0, enc_out_a0
707         .set RA1, enc_out_a1
708         .set RA2, enc_out_a2
709         .set RA3, enc_out_a3
710         .set RB0, enc_out_b0
711         .set RB1, enc_out_b1
712         .set RB2, enc_out_b2
713         .set RB3, enc_out_b3
714
715         vpxor (0 * 32)(%rdx), RA0, RA0;
716         vpxor (1 * 32)(%rdx), RA1, RA1;
717         vpxor (2 * 32)(%rdx), RA2, RA2;
718         vpxor (3 * 32)(%rdx), RA3, RA3;
719         vpxor (4 * 32)(%rdx), RB0, RB0;
720         vpxor (5 * 32)(%rdx), RB1, RB1;
721         vpxor (6 * 32)(%rdx), RB2, RB2;
722         vpxor (7 * 32)(%rdx), RB3, RB3;
723
724         vmovdqu RA0, (0 * 32)(%rsi);
725         vmovdqu RA1, (1 * 32)(%rsi);
726         vmovdqu RA2, (2 * 32)(%rsi);
727         vmovdqu RA3, (3 * 32)(%rsi);
728         vmovdqu RB0, (4 * 32)(%rsi);
729         vmovdqu RB1, (5 * 32)(%rsi);
730         vmovdqu RB2, (6 * 32)(%rsi);
731         vmovdqu RB3, (7 * 32)(%rsi);
732
733         vzeroall;
734
735         ret
736 .size _gcry_serpent_avx2_ctr_enc,.-_gcry_serpent_avx2_ctr_enc;
737
738 .align 8
739 .global _gcry_serpent_avx2_cbc_dec
740 .type   _gcry_serpent_avx2_cbc_dec,@function;
741 _gcry_serpent_avx2_cbc_dec:
742         /* input:
743          *      %rdi: ctx, CTX
744          *      %rsi: dst (16 blocks)
745          *      %rdx: src (16 blocks)
746          *      %rcx: iv
747          */
748
749         vzeroupper;
750
751         .set RA0, dec_in_a0
752         .set RA1, dec_in_a1
753         .set RA2, dec_in_a2
754         .set RA3, dec_in_a3
755         .set RB0, dec_in_b0
756         .set RB1, dec_in_b1
757         .set RB2, dec_in_b2
758         .set RB3, dec_in_b3
759
760         vmovdqu (0 * 32)(%rdx), RA0;
761         vmovdqu (1 * 32)(%rdx), RA1;
762         vmovdqu (2 * 32)(%rdx), RA2;
763         vmovdqu (3 * 32)(%rdx), RA3;
764         vmovdqu (4 * 32)(%rdx), RB0;
765         vmovdqu (5 * 32)(%rdx), RB1;
766         vmovdqu (6 * 32)(%rdx), RB2;
767         vmovdqu (7 * 32)(%rdx), RB3;
768
769         call __serpent_dec_blk16;
770
771         .set RA0, dec_out_a0
772         .set RA1, dec_out_a1
773         .set RA2, dec_out_a2
774         .set RA3, dec_out_a3
775         .set RB0, dec_out_b0
776         .set RB1, dec_out_b1
777         .set RB2, dec_out_b2
778         .set RB3, dec_out_b3
779
780         vmovdqu (%rcx), RNOTx;
781         vinserti128 $1, (%rdx), RNOT, RNOT;
782         vpxor RNOT, RA0, RA0;
783         vpxor (0 * 32 + 16)(%rdx), RA1, RA1;
784         vpxor (1 * 32 + 16)(%rdx), RA2, RA2;
785         vpxor (2 * 32 + 16)(%rdx), RA3, RA3;
786         vpxor (3 * 32 + 16)(%rdx), RB0, RB0;
787         vpxor (4 * 32 + 16)(%rdx), RB1, RB1;
788         vpxor (5 * 32 + 16)(%rdx), RB2, RB2;
789         vpxor (6 * 32 + 16)(%rdx), RB3, RB3;
790         vmovdqu (7 * 32 + 16)(%rdx), RNOTx;
791         vmovdqu RNOTx, (%rcx); /* store new IV */
792
793         vmovdqu RA0, (0 * 32)(%rsi);
794         vmovdqu RA1, (1 * 32)(%rsi);
795         vmovdqu RA2, (2 * 32)(%rsi);
796         vmovdqu RA3, (3 * 32)(%rsi);
797         vmovdqu RB0, (4 * 32)(%rsi);
798         vmovdqu RB1, (5 * 32)(%rsi);
799         vmovdqu RB2, (6 * 32)(%rsi);
800         vmovdqu RB3, (7 * 32)(%rsi);
801
802         vzeroall;
803
804         ret
805 .size _gcry_serpent_avx2_cbc_dec,.-_gcry_serpent_avx2_cbc_dec;
806
807 .align 8
808 .global _gcry_serpent_avx2_cfb_dec
809 .type   _gcry_serpent_avx2_cfb_dec,@function;
810 _gcry_serpent_avx2_cfb_dec:
811         /* input:
812          *      %rdi: ctx, CTX
813          *      %rsi: dst (16 blocks)
814          *      %rdx: src (16 blocks)
815          *      %rcx: iv
816          */
817
818         vzeroupper;
819
820         .set RA0, enc_in_a0
821         .set RA1, enc_in_a1
822         .set RA2, enc_in_a2
823         .set RA3, enc_in_a3
824         .set RB0, enc_in_b0
825         .set RB1, enc_in_b1
826         .set RB2, enc_in_b2
827         .set RB3, enc_in_b3
828
829         /* Load input */
830         vmovdqu (%rcx), RNOTx;
831         vinserti128 $1, (%rdx), RNOT, RA0;
832         vmovdqu (0 * 32 + 16)(%rdx), RA1;
833         vmovdqu (1 * 32 + 16)(%rdx), RA2;
834         vmovdqu (2 * 32 + 16)(%rdx), RA3;
835         vmovdqu (3 * 32 + 16)(%rdx), RB0;
836         vmovdqu (4 * 32 + 16)(%rdx), RB1;
837         vmovdqu (5 * 32 + 16)(%rdx), RB2;
838         vmovdqu (6 * 32 + 16)(%rdx), RB3;
839
840         /* Update IV */
841         vmovdqu (7 * 32 + 16)(%rdx), RNOTx;
842         vmovdqu RNOTx, (%rcx);
843
844         call __serpent_enc_blk16;
845
846         .set RA0, enc_out_a0
847         .set RA1, enc_out_a1
848         .set RA2, enc_out_a2
849         .set RA3, enc_out_a3
850         .set RB0, enc_out_b0
851         .set RB1, enc_out_b1
852         .set RB2, enc_out_b2
853         .set RB3, enc_out_b3
854
855         vpxor (0 * 32)(%rdx), RA0, RA0;
856         vpxor (1 * 32)(%rdx), RA1, RA1;
857         vpxor (2 * 32)(%rdx), RA2, RA2;
858         vpxor (3 * 32)(%rdx), RA3, RA3;
859         vpxor (4 * 32)(%rdx), RB0, RB0;
860         vpxor (5 * 32)(%rdx), RB1, RB1;
861         vpxor (6 * 32)(%rdx), RB2, RB2;
862         vpxor (7 * 32)(%rdx), RB3, RB3;
863
864         vmovdqu RA0, (0 * 32)(%rsi);
865         vmovdqu RA1, (1 * 32)(%rsi);
866         vmovdqu RA2, (2 * 32)(%rsi);
867         vmovdqu RA3, (3 * 32)(%rsi);
868         vmovdqu RB0, (4 * 32)(%rsi);
869         vmovdqu RB1, (5 * 32)(%rsi);
870         vmovdqu RB2, (6 * 32)(%rsi);
871         vmovdqu RB3, (7 * 32)(%rsi);
872
873         vzeroall;
874
875         ret
876 .size _gcry_serpent_avx2_cfb_dec,.-_gcry_serpent_avx2_cfb_dec;
877
878 .data
879 .align 16
880
881 /* For CTR-mode IV byteswap */
882 .Lbswap128_mask:
883         .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
884
885 #endif /*defined(USE_SERPENT) && defined(ENABLE_AVX2_SUPPORT)*/
886 #endif /*__x86_64*/