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