Add crypto hash SM3.
[libgcrypt.git] / cipher / serpent-avx2-amd64.S
1 /* serpent-avx2-amd64.S  -  AVX2 implementation of Serpent cipher
2  *
3  * Copyright (C) 2013-2015 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_SERPENT) && \
25     defined(ENABLE_AVX2_SUPPORT)
26
27 #ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
28 # define ELF(...) __VA_ARGS__
29 #else
30 # define ELF(...) /*_*/
31 #endif
32
33 #ifdef __PIC__
34 #  define RIP (%rip)
35 #else
36 #  define RIP
37 #endif
38
39 /* struct serpent_context: */
40 #define ctx_keys 0
41
42 /* register macros */
43 #define CTX %rdi
44
45 /* vector registers */
46 #define RA0 %ymm0
47 #define RA1 %ymm1
48 #define RA2 %ymm2
49 #define RA3 %ymm3
50 #define RA4 %ymm4
51
52 #define RB0 %ymm5
53 #define RB1 %ymm6
54 #define RB2 %ymm7
55 #define RB3 %ymm8
56 #define RB4 %ymm9
57
58 #define RNOT %ymm10
59 #define RTMP0 %ymm11
60 #define RTMP1 %ymm12
61 #define RTMP2 %ymm13
62 #define RTMP3 %ymm14
63 #define RTMP4 %ymm15
64
65 #define RNOTx %xmm10
66 #define RTMP0x %xmm11
67 #define RTMP1x %xmm12
68 #define RTMP2x %xmm13
69 #define RTMP3x %xmm14
70 #define RTMP4x %xmm15
71
72 /**********************************************************************
73   helper macros
74  **********************************************************************/
75
76 /* vector 32-bit rotation to left */
77 #define vec_rol(reg, nleft, tmp) \
78         vpslld $(nleft), reg, tmp;              \
79         vpsrld $(32 - (nleft)), reg, reg;       \
80         vpor tmp, reg, reg;
81
82 /* vector 32-bit rotation to right */
83 #define vec_ror(reg, nright, tmp) \
84         vec_rol(reg, 32 - nright, tmp)
85
86 /* 4x4 32-bit integer matrix transpose */
87 #define transpose_4x4(x0, x1, x2, x3, t1, t2, t3) \
88         vpunpckhdq x1, x0, t2; \
89         vpunpckldq x1, x0, x0; \
90         \
91         vpunpckldq x3, x2, t1; \
92         vpunpckhdq x3, x2, x2; \
93         \
94         vpunpckhqdq t1, x0, x1; \
95         vpunpcklqdq t1, x0, x0; \
96         \
97         vpunpckhqdq x2, t2, x3; \
98         vpunpcklqdq x2, t2, x2;
99
100 /**********************************************************************
101   16-way serpent
102  **********************************************************************/
103
104 /*
105  * These are the S-Boxes of Serpent from following research paper.
106  *
107  *  D. A. Osvik, “Speeding up Serpent,” in Third AES Candidate Conference,
108  *   (New York, New York, USA), p. 317–329, National Institute of Standards and
109  *   Technology, 2000.
110  *
111  * Paper is also available at: http://www.ii.uib.no/~osvik/pub/aes3.pdf
112  *
113  */
114 #define SBOX0(r0, r1, r2, r3, r4) \
115         vpxor   r0, r3, r3;             vmovdqa r1, r4;                 \
116         vpand   r3, r1, r1;             vpxor   r2, r4, r4;             \
117         vpxor   r0, r1, r1;             vpor    r3, r0, r0;             \
118         vpxor   r4, r0, r0;             vpxor   r3, r4, r4;             \
119         vpxor   r2, r3, r3;             vpor    r1, r2, r2;             \
120         vpxor   r4, r2, r2;             vpxor   RNOT, r4, r4;           \
121         vpor    r1, r4, r4;             vpxor   r3, r1, r1;             \
122         vpxor   r4, r1, r1;             vpor    r0, r3, r3;             \
123         vpxor   r3, r1, r1;             vpxor   r3, r4, r4;
124
125 #define SBOX0_INVERSE(r0, r1, r2, r3, r4) \
126         vpxor   RNOT, r2, r2;           vmovdqa r1, r4;                 \
127         vpor    r0, r1, r1;             vpxor   RNOT, r4, r4;           \
128         vpxor   r2, r1, r1;             vpor    r4, r2, r2;             \
129         vpxor   r3, r1, r1;             vpxor   r4, r0, r0;             \
130         vpxor   r0, r2, r2;             vpand   r3, r0, r0;             \
131         vpxor   r0, r4, r4;             vpor    r1, r0, r0;             \
132         vpxor   r2, r0, r0;             vpxor   r4, r3, r3;             \
133         vpxor   r1, r2, r2;             vpxor   r0, r3, r3;             \
134         vpxor   r1, r3, r3;     \
135         vpand   r3, r2, r2;     \
136         vpxor   r2, r4, r4;
137
138 #define SBOX1(r0, r1, r2, r3, r4) \
139         vpxor   RNOT, r0, r0;           vpxor   RNOT, r2, r2;           \
140         vmovdqa r0, r4;                 vpand   r1, r0, r0;             \
141         vpxor   r0, r2, r2;             vpor    r3, r0, r0;             \
142         vpxor   r2, r3, r3;             vpxor   r0, r1, r1;             \
143         vpxor   r4, r0, r0;             vpor    r1, r4, r4;             \
144         vpxor   r3, r1, r1;             vpor    r0, r2, r2;             \
145         vpand   r4, r2, r2;             vpxor   r1, r0, r0;             \
146         vpand   r2, r1, r1;     \
147         vpxor   r0, r1, r1;             vpand   r2, r0, r0;             \
148         vpxor   r4, r0, r0;
149
150 #define SBOX1_INVERSE(r0, r1, r2, r3, r4) \
151         vmovdqa r1, r4;                 vpxor   r3, r1, r1;             \
152         vpand   r1, r3, r3;             vpxor   r2, r4, r4;             \
153         vpxor   r0, r3, r3;             vpor    r1, r0, r0;             \
154         vpxor   r3, r2, r2;             vpxor   r4, r0, r0;             \
155         vpor    r2, r0, r0;             vpxor   r3, r1, r1;             \
156         vpxor   r1, r0, r0;             vpor    r3, r1, r1;             \
157         vpxor   r0, r1, r1;             vpxor   RNOT, r4, r4;           \
158         vpxor   r1, r4, r4;             vpor    r0, r1, r1;             \
159         vpxor   r0, r1, r1;     \
160         vpor    r4, r1, r1;     \
161         vpxor   r1, r3, r3;
162
163 #define SBOX2(r0, r1, r2, r3, r4) \
164         vmovdqa r0, r4;                 vpand   r2, r0, r0;             \
165         vpxor   r3, r0, r0;             vpxor   r1, r2, r2;             \
166         vpxor   r0, r2, r2;             vpor    r4, r3, r3;             \
167         vpxor   r1, r3, r3;             vpxor   r2, r4, r4;             \
168         vmovdqa r3, r1;                 vpor    r4, r3, r3;             \
169         vpxor   r0, r3, r3;             vpand   r1, r0, r0;             \
170         vpxor   r0, r4, r4;             vpxor   r3, r1, r1;             \
171         vpxor   r4, r1, r1;             vpxor   RNOT, r4, r4;
172
173 #define SBOX2_INVERSE(r0, r1, r2, r3, r4) \
174         vpxor   r3, r2, r2;             vpxor   r0, r3, r3;             \
175         vmovdqa r3, r4;                 vpand   r2, r3, r3;             \
176         vpxor   r1, r3, r3;             vpor    r2, r1, r1;             \
177         vpxor   r4, r1, r1;             vpand   r3, r4, r4;             \
178         vpxor   r3, r2, r2;             vpand   r0, r4, r4;             \
179         vpxor   r2, r4, r4;             vpand   r1, r2, r2;             \
180         vpor    r0, r2, r2;             vpxor   RNOT, r3, r3;           \
181         vpxor   r3, r2, r2;             vpxor   r3, r0, r0;             \
182         vpand   r1, r0, r0;             vpxor   r4, r3, r3;             \
183         vpxor   r0, r3, r3;
184
185 #define SBOX3(r0, r1, r2, r3, r4) \
186         vmovdqa r0, r4;                 vpor    r3, r0, r0;             \
187         vpxor   r1, r3, r3;             vpand   r4, r1, r1;             \
188         vpxor   r2, r4, r4;             vpxor   r3, r2, r2;             \
189         vpand   r0, r3, r3;             vpor    r1, r4, r4;             \
190         vpxor   r4, r3, r3;             vpxor   r1, r0, r0;             \
191         vpand   r0, r4, r4;             vpxor   r3, r1, r1;             \
192         vpxor   r2, r4, r4;             vpor    r0, r1, r1;             \
193         vpxor   r2, r1, r1;             vpxor   r3, r0, r0;             \
194         vmovdqa r1, r2;                 vpor    r3, r1, r1;             \
195         vpxor   r0, r1, r1;
196
197 #define SBOX3_INVERSE(r0, r1, r2, r3, r4) \
198         vmovdqa r2, r4;                 vpxor   r1, r2, r2;             \
199         vpxor   r2, r0, r0;             vpand   r2, r4, r4;             \
200         vpxor   r0, r4, r4;             vpand   r1, r0, r0;             \
201         vpxor   r3, r1, r1;             vpor    r4, r3, r3;             \
202         vpxor   r3, r2, r2;             vpxor   r3, r0, r0;             \
203         vpxor   r4, r1, r1;             vpand   r2, r3, r3;             \
204         vpxor   r1, r3, r3;             vpxor   r0, r1, r1;             \
205         vpor    r2, r1, r1;             vpxor   r3, r0, r0;             \
206         vpxor   r4, r1, r1;     \
207         vpxor   r1, r0, r0;
208
209 #define SBOX4(r0, r1, r2, r3, r4) \
210         vpxor   r3, r1, r1;             vpxor   RNOT, r3, r3;           \
211         vpxor   r3, r2, r2;             vpxor   r0, r3, r3;             \
212         vmovdqa r1, r4;                 vpand   r3, r1, r1;             \
213         vpxor   r2, r1, r1;             vpxor   r3, r4, r4;             \
214         vpxor   r4, r0, r0;             vpand   r4, r2, r2;             \
215         vpxor   r0, r2, r2;             vpand   r1, r0, r0;             \
216         vpxor   r0, r3, r3;             vpor    r1, r4, r4;             \
217         vpxor   r0, r4, r4;             vpor    r3, r0, r0;             \
218         vpxor   r2, r0, r0;             vpand   r3, r2, r2;             \
219         vpxor   RNOT, r0, r0;           vpxor   r2, r4, r4;
220
221 #define SBOX4_INVERSE(r0, r1, r2, r3, r4) \
222         vmovdqa r2, r4;                 vpand   r3, r2, r2;             \
223         vpxor   r1, r2, r2;             vpor    r3, r1, r1;             \
224         vpand   r0, r1, r1;             vpxor   r2, r4, r4;             \
225         vpxor   r1, r4, r4;             vpand   r2, r1, r1;             \
226         vpxor   RNOT, r0, r0;           vpxor   r4, r3, r3;             \
227         vpxor   r3, r1, r1;             vpand   r0, r3, r3;             \
228         vpxor   r2, r3, r3;             vpxor   r1, r0, r0;             \
229         vpand   r0, r2, r2;             vpxor   r0, r3, r3;             \
230         vpxor   r4, r2, r2;     \
231         vpor    r3, r2, r2;             vpxor   r0, r3, r3;             \
232         vpxor   r1, r2, r2;
233
234 #define SBOX5(r0, r1, r2, r3, r4) \
235         vpxor   r1, r0, r0;             vpxor   r3, r1, r1;             \
236         vpxor   RNOT, r3, r3;           vmovdqa r1, r4;                 \
237         vpand   r0, r1, r1;             vpxor   r3, r2, r2;             \
238         vpxor   r2, r1, r1;             vpor    r4, r2, r2;             \
239         vpxor   r3, r4, r4;             vpand   r1, r3, r3;             \
240         vpxor   r0, r3, r3;             vpxor   r1, r4, r4;             \
241         vpxor   r2, r4, r4;             vpxor   r0, r2, r2;             \
242         vpand   r3, r0, r0;             vpxor   RNOT, r2, r2;           \
243         vpxor   r4, r0, r0;             vpor    r3, r4, r4;             \
244         vpxor   r4, r2, r2;
245
246 #define SBOX5_INVERSE(r0, r1, r2, r3, r4) \
247         vpxor   RNOT, r1, r1;           vmovdqa r3, r4;                 \
248         vpxor   r1, r2, r2;             vpor    r0, r3, r3;             \
249         vpxor   r2, r3, r3;             vpor    r1, r2, r2;             \
250         vpand   r0, r2, r2;             vpxor   r3, r4, r4;             \
251         vpxor   r4, r2, r2;             vpor    r0, r4, r4;             \
252         vpxor   r1, r4, r4;             vpand   r2, r1, r1;             \
253         vpxor   r3, r1, r1;             vpxor   r2, r4, r4;             \
254         vpand   r4, r3, r3;             vpxor   r1, r4, r4;             \
255         vpxor   r4, r3, r3;             vpxor   RNOT, r4, r4;           \
256         vpxor   r0, r3, r3;
257
258 #define SBOX6(r0, r1, r2, r3, r4) \
259         vpxor   RNOT, r2, r2;           vmovdqa r3, r4;                 \
260         vpand   r0, r3, r3;             vpxor   r4, r0, r0;             \
261         vpxor   r2, r3, r3;             vpor    r4, r2, r2;             \
262         vpxor   r3, r1, r1;             vpxor   r0, r2, r2;             \
263         vpor    r1, r0, r0;             vpxor   r1, r2, r2;             \
264         vpxor   r0, r4, r4;             vpor    r3, r0, r0;             \
265         vpxor   r2, r0, r0;             vpxor   r3, r4, r4;             \
266         vpxor   r0, r4, r4;             vpxor   RNOT, r3, r3;           \
267         vpand   r4, r2, r2;     \
268         vpxor   r3, r2, r2;
269
270 #define SBOX6_INVERSE(r0, r1, r2, r3, r4) \
271         vpxor   r2, r0, r0;             vmovdqa r2, r4;                 \
272         vpand   r0, r2, r2;             vpxor   r3, r4, r4;             \
273         vpxor   RNOT, r2, r2;           vpxor   r1, r3, r3;             \
274         vpxor   r3, r2, r2;             vpor    r0, r4, r4;             \
275         vpxor   r2, r0, r0;             vpxor   r4, r3, r3;             \
276         vpxor   r1, r4, r4;             vpand   r3, r1, r1;             \
277         vpxor   r0, r1, r1;             vpxor   r3, r0, r0;             \
278         vpor    r2, r0, r0;             vpxor   r1, r3, r3;             \
279         vpxor   r0, r4, r4;
280
281 #define SBOX7(r0, r1, r2, r3, r4) \
282         vmovdqa r1, r4;                 vpor    r2, r1, r1;             \
283         vpxor   r3, r1, r1;             vpxor   r2, r4, r4;             \
284         vpxor   r1, r2, r2;             vpor    r4, r3, r3;             \
285         vpand   r0, r3, r3;             vpxor   r2, r4, r4;             \
286         vpxor   r1, r3, r3;             vpor    r4, r1, r1;             \
287         vpxor   r0, r1, r1;             vpor    r4, r0, r0;             \
288         vpxor   r2, r0, r0;             vpxor   r4, r1, r1;             \
289         vpxor   r1, r2, r2;             vpand   r0, r1, r1;             \
290         vpxor   r4, r1, r1;             vpxor   RNOT, r2, r2;           \
291         vpor    r0, r2, r2;     \
292         vpxor   r2, r4, r4;
293
294 #define SBOX7_INVERSE(r0, r1, r2, r3, r4) \
295         vmovdqa r2, r4;                 vpxor   r0, r2, r2;             \
296         vpand   r3, r0, r0;             vpor    r3, r4, r4;             \
297         vpxor   RNOT, r2, r2;           vpxor   r1, r3, r3;             \
298         vpor    r0, r1, r1;             vpxor   r2, r0, r0;             \
299         vpand   r4, r2, r2;             vpand   r4, r3, r3;             \
300         vpxor   r2, r1, r1;             vpxor   r0, r2, r2;             \
301         vpor    r2, r0, r0;             vpxor   r1, r4, r4;             \
302         vpxor   r3, r0, r0;             vpxor   r4, r3, r3;             \
303         vpor    r0, r4, r4;             vpxor   r2, r3, r3;             \
304         vpxor   r2, r4, r4;
305
306 /* Apply SBOX number WHICH to to the block.  */
307 #define SBOX(which, r0, r1, r2, r3, r4) \
308         SBOX##which (r0, r1, r2, r3, r4)
309
310 /* Apply inverse SBOX number WHICH to to the block.  */
311 #define SBOX_INVERSE(which, r0, r1, r2, r3, r4) \
312         SBOX##which##_INVERSE (r0, r1, r2, r3, r4)
313
314 /* XOR round key into block state in r0,r1,r2,r3. r4 used as temporary.  */
315 #define BLOCK_XOR_KEY(r0, r1, r2, r3, r4, round) \
316         vpbroadcastd (ctx_keys + (round) * 16 + 0 * 4)(CTX), r4; \
317         vpxor r4, r0, r0; \
318         vpbroadcastd (ctx_keys + (round) * 16 + 1 * 4)(CTX), r4; \
319         vpxor r4, r1, r1; \
320         vpbroadcastd (ctx_keys + (round) * 16 + 2 * 4)(CTX), r4; \
321         vpxor r4, r2, r2; \
322         vpbroadcastd (ctx_keys + (round) * 16 + 3 * 4)(CTX), r4; \
323         vpxor r4, r3, r3;
324
325 /* Apply the linear transformation to BLOCK.  */
326 #define LINEAR_TRANSFORMATION(r0, r1, r2, r3, r4) \
327         vec_rol(r0, 13, r4);    \
328         vec_rol(r2, 3, r4);     \
329         vpxor r0, r1, r1;       \
330         vpxor r2, r1, r1;       \
331         vpslld $3, r0, r4;      \
332         vpxor r2, r3, r3;       \
333         vpxor r4, r3, r3;       \
334         vec_rol(r1, 1, r4);     \
335         vec_rol(r3, 7, r4);     \
336         vpxor r1, r0, r0;       \
337         vpxor r3, r0, r0;       \
338         vpslld $7, r1, r4;      \
339         vpxor r3, r2, r2;       \
340         vpxor r4, r2, r2;       \
341         vec_rol(r0, 5, r4);     \
342         vec_rol(r2, 22, r4);
343
344 /* Apply the inverse linear transformation to BLOCK.  */
345 #define LINEAR_TRANSFORMATION_INVERSE(r0, r1, r2, r3, r4) \
346         vec_ror(r2, 22, r4);    \
347         vec_ror(r0, 5, r4);     \
348         vpslld $7, r1, r4;      \
349         vpxor r3, r2, r2;       \
350         vpxor r4, r2, r2;       \
351         vpxor r1, r0, r0;       \
352         vpxor r3, r0, r0;       \
353         vec_ror(r3, 7, r4);     \
354         vec_ror(r1, 1, r4);     \
355         vpslld $3, r0, r4;      \
356         vpxor r2, r3, r3;       \
357         vpxor r4, r3, r3;       \
358         vpxor r0, r1, r1;       \
359         vpxor r2, r1, r1;       \
360         vec_ror(r2, 3, r4);     \
361         vec_ror(r0, 13, r4);
362
363 /* Apply a Serpent round to sixteen parallel blocks.  This macro increments
364    `round'.  */
365 #define ROUND(round, which, a0, a1, a2, a3, a4, na0, na1, na2, na3, na4, \
366                             b0, b1, b2, b3, b4, nb0, nb1, nb2, nb3, nb4) \
367         BLOCK_XOR_KEY (a0, a1, a2, a3, a4, round);              \
368         SBOX (which, a0, a1, a2, a3, a4);                       \
369                 BLOCK_XOR_KEY (b0, b1, b2, b3, b4, round);              \
370                 SBOX (which, b0, b1, b2, b3, b4);                       \
371         LINEAR_TRANSFORMATION (na0, na1, na2, na3, na4);        \
372                 LINEAR_TRANSFORMATION (nb0, nb1, nb2, nb3, nb4);
373
374 /* Apply the last Serpent round to sixteen parallel blocks.  This macro
375    increments `round'.  */
376 #define ROUND_LAST(round, which, a0, a1, a2, a3, a4, na0, na1, na2, na3, na4, \
377                                  b0, b1, b2, b3, b4, nb0, nb1, nb2, nb3, nb4) \
378         BLOCK_XOR_KEY (a0, a1, a2, a3, a4, round);              \
379         SBOX (which, a0, a1, a2, a3, a4);                       \
380                 BLOCK_XOR_KEY (b0, b1, b2, b3, b4, round);              \
381                 SBOX (which, b0, b1, b2, b3, b4);                       \
382         BLOCK_XOR_KEY (na0, na1, na2, na3, na4, ((round) + 1));         \
383                 BLOCK_XOR_KEY (nb0, nb1, nb2, nb3, nb4, ((round) + 1));
384
385 /* Apply an inverse Serpent round to sixteen parallel blocks.  This macro
386    increments `round'.  */
387 #define ROUND_INVERSE(round, which, a0, a1, a2, a3, a4, \
388                                     na0, na1, na2, na3, na4, \
389                                     b0, b1, b2, b3, b4, \
390                                     nb0, nb1, nb2, nb3, nb4) \
391         LINEAR_TRANSFORMATION_INVERSE (a0, a1, a2, a3, a4);     \
392                 LINEAR_TRANSFORMATION_INVERSE (b0, b1, b2, b3, b4);     \
393         SBOX_INVERSE (which, a0, a1, a2, a3, a4);               \
394         BLOCK_XOR_KEY (na0, na1, na2, na3, na4, round);         \
395                 SBOX_INVERSE (which, b0, b1, b2, b3, b4);               \
396                 BLOCK_XOR_KEY (nb0, nb1, nb2, nb3, nb4, round);
397
398 /* Apply the first inverse Serpent round to sixteen parallel blocks.  This macro
399    increments `round'.  */
400 #define ROUND_FIRST_INVERSE(round, which, a0, a1, a2, a3, a4, \
401                                           na0, na1, na2, na3, na4, \
402                                           b0, b1, b2, b3, b4, \
403                                           nb0, nb1, nb2, nb3, nb4) \
404         BLOCK_XOR_KEY (a0, a1, a2, a3, a4, ((round) + 1));      \
405                 BLOCK_XOR_KEY (b0, b1, b2, b3, b4, ((round) + 1));      \
406         SBOX_INVERSE (which, a0, a1, a2, a3, a4);       \
407         BLOCK_XOR_KEY (na0, na1, na2, na3, na4, round); \
408                 SBOX_INVERSE (which, b0, b1, b2, b3, b4);       \
409                 BLOCK_XOR_KEY (nb0, nb1, nb2, nb3, nb4, round);
410
411 .text
412
413 .align 8
414 ELF(.type   __serpent_enc_blk16,@function;)
415 __serpent_enc_blk16:
416         /* input:
417          *      %rdi: ctx, CTX
418          *      RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: sixteen parallel
419          *                                              plaintext blocks
420          * output:
421          *      RA4, RA1, RA2, RA0, RB4, RB1, RB2, RB0: sixteen parallel
422          *                                              ciphertext blocks
423          */
424
425         vpcmpeqd RNOT, RNOT, RNOT;
426
427         transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
428         transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
429
430         ROUND (0, 0, RA0, RA1, RA2, RA3, RA4, RA1, RA4, RA2, RA0, RA3,
431                      RB0, RB1, RB2, RB3, RB4, RB1, RB4, RB2, RB0, RB3);
432         ROUND (1, 1, RA1, RA4, RA2, RA0, RA3, RA2, RA1, RA0, RA4, RA3,
433                      RB1, RB4, RB2, RB0, RB3, RB2, RB1, RB0, RB4, RB3);
434         ROUND (2, 2, RA2, RA1, RA0, RA4, RA3, RA0, RA4, RA1, RA3, RA2,
435                      RB2, RB1, RB0, RB4, RB3, RB0, RB4, RB1, RB3, RB2);
436         ROUND (3, 3, RA0, RA4, RA1, RA3, RA2, RA4, RA1, RA3, RA2, RA0,
437                      RB0, RB4, RB1, RB3, RB2, RB4, RB1, RB3, RB2, RB0);
438         ROUND (4, 4, RA4, RA1, RA3, RA2, RA0, RA1, RA0, RA4, RA2, RA3,
439                      RB4, RB1, RB3, RB2, RB0, RB1, RB0, RB4, RB2, RB3);
440         ROUND (5, 5, RA1, RA0, RA4, RA2, RA3, RA0, RA2, RA1, RA4, RA3,
441                      RB1, RB0, RB4, RB2, RB3, RB0, RB2, RB1, RB4, RB3);
442         ROUND (6, 6, RA0, RA2, RA1, RA4, RA3, RA0, RA2, RA3, RA1, RA4,
443                      RB0, RB2, RB1, RB4, RB3, RB0, RB2, RB3, RB1, RB4);
444         ROUND (7, 7, RA0, RA2, RA3, RA1, RA4, RA4, RA1, RA2, RA0, RA3,
445                      RB0, RB2, RB3, RB1, RB4, RB4, RB1, RB2, RB0, RB3);
446         ROUND (8, 0, RA4, RA1, RA2, RA0, RA3, RA1, RA3, RA2, RA4, RA0,
447                      RB4, RB1, RB2, RB0, RB3, RB1, RB3, RB2, RB4, RB0);
448         ROUND (9, 1, RA1, RA3, RA2, RA4, RA0, RA2, RA1, RA4, RA3, RA0,
449                      RB1, RB3, RB2, RB4, RB0, RB2, RB1, RB4, RB3, RB0);
450         ROUND (10, 2, RA2, RA1, RA4, RA3, RA0, RA4, RA3, RA1, RA0, RA2,
451                       RB2, RB1, RB4, RB3, RB0, RB4, RB3, RB1, RB0, RB2);
452         ROUND (11, 3, RA4, RA3, RA1, RA0, RA2, RA3, RA1, RA0, RA2, RA4,
453                       RB4, RB3, RB1, RB0, RB2, RB3, RB1, RB0, RB2, RB4);
454         ROUND (12, 4, RA3, RA1, RA0, RA2, RA4, RA1, RA4, RA3, RA2, RA0,
455                       RB3, RB1, RB0, RB2, RB4, RB1, RB4, RB3, RB2, RB0);
456         ROUND (13, 5, RA1, RA4, RA3, RA2, RA0, RA4, RA2, RA1, RA3, RA0,
457                       RB1, RB4, RB3, RB2, RB0, RB4, RB2, RB1, RB3, RB0);
458         ROUND (14, 6, RA4, RA2, RA1, RA3, RA0, RA4, RA2, RA0, RA1, RA3,
459                       RB4, RB2, RB1, RB3, RB0, RB4, RB2, RB0, RB1, RB3);
460         ROUND (15, 7, RA4, RA2, RA0, RA1, RA3, RA3, RA1, RA2, RA4, RA0,
461                       RB4, RB2, RB0, RB1, RB3, RB3, RB1, RB2, RB4, RB0);
462         ROUND (16, 0, RA3, RA1, RA2, RA4, RA0, RA1, RA0, RA2, RA3, RA4,
463                       RB3, RB1, RB2, RB4, RB0, RB1, RB0, RB2, RB3, RB4);
464         ROUND (17, 1, RA1, RA0, RA2, RA3, RA4, RA2, RA1, RA3, RA0, RA4,
465                       RB1, RB0, RB2, RB3, RB4, RB2, RB1, RB3, RB0, RB4);
466         ROUND (18, 2, RA2, RA1, RA3, RA0, RA4, RA3, RA0, RA1, RA4, RA2,
467                       RB2, RB1, RB3, RB0, RB4, RB3, RB0, RB1, RB4, RB2);
468         ROUND (19, 3, RA3, RA0, RA1, RA4, RA2, RA0, RA1, RA4, RA2, RA3,
469                       RB3, RB0, RB1, RB4, RB2, RB0, RB1, RB4, RB2, RB3);
470         ROUND (20, 4, RA0, RA1, RA4, RA2, RA3, RA1, RA3, RA0, RA2, RA4,
471                       RB0, RB1, RB4, RB2, RB3, RB1, RB3, RB0, RB2, RB4);
472         ROUND (21, 5, RA1, RA3, RA0, RA2, RA4, RA3, RA2, RA1, RA0, RA4,
473                       RB1, RB3, RB0, RB2, RB4, RB3, RB2, RB1, RB0, RB4);
474         ROUND (22, 6, RA3, RA2, RA1, RA0, RA4, RA3, RA2, RA4, RA1, RA0,
475                       RB3, RB2, RB1, RB0, RB4, RB3, RB2, RB4, RB1, RB0);
476         ROUND (23, 7, RA3, RA2, RA4, RA1, RA0, RA0, RA1, RA2, RA3, RA4,
477                       RB3, RB2, RB4, RB1, RB0, RB0, RB1, RB2, RB3, RB4);
478         ROUND (24, 0, RA0, RA1, RA2, RA3, RA4, RA1, RA4, RA2, RA0, RA3,
479                       RB0, RB1, RB2, RB3, RB4, RB1, RB4, RB2, RB0, RB3);
480         ROUND (25, 1, RA1, RA4, RA2, RA0, RA3, RA2, RA1, RA0, RA4, RA3,
481                       RB1, RB4, RB2, RB0, RB3, RB2, RB1, RB0, RB4, RB3);
482         ROUND (26, 2, RA2, RA1, RA0, RA4, RA3, RA0, RA4, RA1, RA3, RA2,
483                       RB2, RB1, RB0, RB4, RB3, RB0, RB4, RB1, RB3, RB2);
484         ROUND (27, 3, RA0, RA4, RA1, RA3, RA2, RA4, RA1, RA3, RA2, RA0,
485                       RB0, RB4, RB1, RB3, RB2, RB4, RB1, RB3, RB2, RB0);
486         ROUND (28, 4, RA4, RA1, RA3, RA2, RA0, RA1, RA0, RA4, RA2, RA3,
487                       RB4, RB1, RB3, RB2, RB0, RB1, RB0, RB4, RB2, RB3);
488         ROUND (29, 5, RA1, RA0, RA4, RA2, RA3, RA0, RA2, RA1, RA4, RA3,
489                       RB1, RB0, RB4, RB2, RB3, RB0, RB2, RB1, RB4, RB3);
490         ROUND (30, 6, RA0, RA2, RA1, RA4, RA3, RA0, RA2, RA3, RA1, RA4,
491                       RB0, RB2, RB1, RB4, RB3, RB0, RB2, RB3, RB1, RB4);
492         ROUND_LAST (31, 7, RA0, RA2, RA3, RA1, RA4, RA4, RA1, RA2, RA0, RA3,
493                            RB0, RB2, RB3, RB1, RB4, RB4, RB1, RB2, RB0, RB3);
494
495         transpose_4x4(RA4, RA1, RA2, RA0, RA3, RTMP0, RTMP1);
496         transpose_4x4(RB4, RB1, RB2, RB0, RB3, RTMP0, RTMP1);
497
498         ret;
499 ELF(.size __serpent_enc_blk16,.-__serpent_enc_blk16;)
500
501 .align 8
502 ELF(.type   __serpent_dec_blk16,@function;)
503 __serpent_dec_blk16:
504         /* input:
505          *      %rdi: ctx, CTX
506          *      RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: sixteen parallel
507          *                                              ciphertext blocks
508          * output:
509          *      RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: sixteen parallel
510          *                                              plaintext blocks
511          */
512
513         vpcmpeqd RNOT, RNOT, RNOT;
514
515         transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
516         transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
517
518         ROUND_FIRST_INVERSE (31, 7, RA0, RA1, RA2, RA3, RA4,
519                                     RA3, RA0, RA1, RA4, RA2,
520                                     RB0, RB1, RB2, RB3, RB4,
521                                     RB3, RB0, RB1, RB4, RB2);
522         ROUND_INVERSE (30, 6, RA3, RA0, RA1, RA4, RA2, RA0, RA1, RA2, RA4, RA3,
523                               RB3, RB0, RB1, RB4, RB2, RB0, RB1, RB2, RB4, RB3);
524         ROUND_INVERSE (29, 5, RA0, RA1, RA2, RA4, RA3, RA1, RA3, RA4, RA2, RA0,
525                               RB0, RB1, RB2, RB4, RB3, RB1, RB3, RB4, RB2, RB0);
526         ROUND_INVERSE (28, 4, RA1, RA3, RA4, RA2, RA0, RA1, RA2, RA4, RA0, RA3,
527                               RB1, RB3, RB4, RB2, RB0, RB1, RB2, RB4, RB0, RB3);
528         ROUND_INVERSE (27, 3, RA1, RA2, RA4, RA0, RA3, RA4, RA2, RA0, RA1, RA3,
529                               RB1, RB2, RB4, RB0, RB3, RB4, RB2, RB0, RB1, RB3);
530         ROUND_INVERSE (26, 2, RA4, RA2, RA0, RA1, RA3, RA2, RA3, RA0, RA1, RA4,
531                               RB4, RB2, RB0, RB1, RB3, RB2, RB3, RB0, RB1, RB4);
532         ROUND_INVERSE (25, 1, RA2, RA3, RA0, RA1, RA4, RA4, RA2, RA1, RA0, RA3,
533                               RB2, RB3, RB0, RB1, RB4, RB4, RB2, RB1, RB0, RB3);
534         ROUND_INVERSE (24, 0, RA4, RA2, RA1, RA0, RA3, RA4, RA3, RA2, RA0, RA1,
535                               RB4, RB2, RB1, RB0, RB3, RB4, RB3, RB2, RB0, RB1);
536         ROUND_INVERSE (23, 7, RA4, RA3, RA2, RA0, RA1, RA0, RA4, RA3, RA1, RA2,
537                               RB4, RB3, RB2, RB0, RB1, RB0, RB4, RB3, RB1, RB2);
538         ROUND_INVERSE (22, 6, RA0, RA4, RA3, RA1, RA2, RA4, RA3, RA2, RA1, RA0,
539                               RB0, RB4, RB3, RB1, RB2, RB4, RB3, RB2, RB1, RB0);
540         ROUND_INVERSE (21, 5, RA4, RA3, RA2, RA1, RA0, RA3, RA0, RA1, RA2, RA4,
541                               RB4, RB3, RB2, RB1, RB0, RB3, RB0, RB1, RB2, RB4);
542         ROUND_INVERSE (20, 4, RA3, RA0, RA1, RA2, RA4, RA3, RA2, RA1, RA4, RA0,
543                               RB3, RB0, RB1, RB2, RB4, RB3, RB2, RB1, RB4, RB0);
544         ROUND_INVERSE (19, 3, RA3, RA2, RA1, RA4, RA0, RA1, RA2, RA4, RA3, RA0,
545                               RB3, RB2, RB1, RB4, RB0, RB1, RB2, RB4, RB3, RB0);
546         ROUND_INVERSE (18, 2, RA1, RA2, RA4, RA3, RA0, RA2, RA0, RA4, RA3, RA1,
547                               RB1, RB2, RB4, RB3, RB0, RB2, RB0, RB4, RB3, RB1);
548         ROUND_INVERSE (17, 1, RA2, RA0, RA4, RA3, RA1, RA1, RA2, RA3, RA4, RA0,
549                               RB2, RB0, RB4, RB3, RB1, RB1, RB2, RB3, RB4, RB0);
550         ROUND_INVERSE (16, 0, RA1, RA2, RA3, RA4, RA0, RA1, RA0, RA2, RA4, RA3,
551                               RB1, RB2, RB3, RB4, RB0, RB1, RB0, RB2, RB4, RB3);
552         ROUND_INVERSE (15, 7, RA1, RA0, RA2, RA4, RA3, RA4, RA1, RA0, RA3, RA2,
553                               RB1, RB0, RB2, RB4, RB3, RB4, RB1, RB0, RB3, RB2);
554         ROUND_INVERSE (14, 6, RA4, RA1, RA0, RA3, RA2, RA1, RA0, RA2, RA3, RA4,
555                               RB4, RB1, RB0, RB3, RB2, RB1, RB0, RB2, RB3, RB4);
556         ROUND_INVERSE (13, 5, RA1, RA0, RA2, RA3, RA4, RA0, RA4, RA3, RA2, RA1,
557                               RB1, RB0, RB2, RB3, RB4, RB0, RB4, RB3, RB2, RB1);
558         ROUND_INVERSE (12, 4, RA0, RA4, RA3, RA2, RA1, RA0, RA2, RA3, RA1, RA4,
559                               RB0, RB4, RB3, RB2, RB1, RB0, RB2, RB3, RB1, RB4);
560         ROUND_INVERSE (11, 3, RA0, RA2, RA3, RA1, RA4, RA3, RA2, RA1, RA0, RA4,
561                               RB0, RB2, RB3, RB1, RB4, RB3, RB2, RB1, RB0, RB4);
562         ROUND_INVERSE (10, 2, RA3, RA2, RA1, RA0, RA4, RA2, RA4, RA1, RA0, RA3,
563                               RB3, RB2, RB1, RB0, RB4, RB2, RB4, RB1, RB0, RB3);
564         ROUND_INVERSE (9, 1, RA2, RA4, RA1, RA0, RA3, RA3, RA2, RA0, RA1, RA4,
565                              RB2, RB4, RB1, RB0, RB3, RB3, RB2, RB0, RB1, RB4);
566         ROUND_INVERSE (8, 0, RA3, RA2, RA0, RA1, RA4, RA3, RA4, RA2, RA1, RA0,
567                              RB3, RB2, RB0, RB1, RB4, RB3, RB4, RB2, RB1, RB0);
568         ROUND_INVERSE (7, 7, RA3, RA4, RA2, RA1, RA0, RA1, RA3, RA4, RA0, RA2,
569                              RB3, RB4, RB2, RB1, RB0, RB1, RB3, RB4, RB0, RB2);
570         ROUND_INVERSE (6, 6, RA1, RA3, RA4, RA0, RA2, RA3, RA4, RA2, RA0, RA1,
571                              RB1, RB3, RB4, RB0, RB2, RB3, RB4, RB2, RB0, RB1);
572         ROUND_INVERSE (5, 5, RA3, RA4, RA2, RA0, RA1, RA4, RA1, RA0, RA2, RA3,
573                              RB3, RB4, RB2, RB0, RB1, RB4, RB1, RB0, RB2, RB3);
574         ROUND_INVERSE (4, 4, RA4, RA1, RA0, RA2, RA3, RA4, RA2, RA0, RA3, RA1,
575                              RB4, RB1, RB0, RB2, RB3, RB4, RB2, RB0, RB3, RB1);
576         ROUND_INVERSE (3, 3, RA4, RA2, RA0, RA3, RA1, RA0, RA2, RA3, RA4, RA1,
577                              RB4, RB2, RB0, RB3, RB1, RB0, RB2, RB3, RB4, RB1);
578         ROUND_INVERSE (2, 2, RA0, RA2, RA3, RA4, RA1, RA2, RA1, RA3, RA4, RA0,
579                              RB0, RB2, RB3, RB4, RB1, RB2, RB1, RB3, RB4, RB0);
580         ROUND_INVERSE (1, 1, RA2, RA1, RA3, RA4, RA0, RA0, RA2, RA4, RA3, RA1,
581                              RB2, RB1, RB3, RB4, RB0, RB0, RB2, RB4, RB3, RB1);
582         ROUND_INVERSE (0, 0, RA0, RA2, RA4, RA3, RA1, RA0, RA1, RA2, RA3, RA4,
583                              RB0, RB2, RB4, RB3, RB1, RB0, RB1, RB2, RB3, RB4);
584
585         transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
586         transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
587
588         ret;
589 ELF(.size __serpent_dec_blk16,.-__serpent_dec_blk16;)
590
591 #define inc_le128(x, minus_one, tmp) \
592         vpcmpeqq minus_one, x, tmp; \
593         vpsubq minus_one, x, x; \
594         vpslldq $8, tmp, tmp; \
595         vpsubq tmp, x, x;
596
597 .align 8
598 .globl _gcry_serpent_avx2_ctr_enc
599 ELF(.type   _gcry_serpent_avx2_ctr_enc,@function;)
600 _gcry_serpent_avx2_ctr_enc:
601         /* input:
602          *      %rdi: ctx, CTX
603          *      %rsi: dst (16 blocks)
604          *      %rdx: src (16 blocks)
605          *      %rcx: iv (big endian, 128bit)
606          */
607
608         movq 8(%rcx), %rax;
609         bswapq %rax;
610
611         vzeroupper;
612
613         vbroadcasti128 .Lbswap128_mask RIP, RTMP3;
614         vpcmpeqd RNOT, RNOT, RNOT;
615         vpsrldq $8, RNOT, RNOT;   /* ab: -1:0 ; cd: -1:0 */
616         vpaddq RNOT, RNOT, RTMP2; /* ab: -2:0 ; cd: -2:0 */
617
618         /* load IV and byteswap */
619         vmovdqu (%rcx), RTMP4x;
620         vpshufb RTMP3x, RTMP4x, RTMP4x;
621         vmovdqa RTMP4x, RTMP0x;
622         inc_le128(RTMP4x, RNOTx, RTMP1x);
623         vinserti128 $1, RTMP4x, RTMP0, RTMP0;
624         vpshufb RTMP3, RTMP0, RA0; /* +1 ; +0 */
625
626         /* check need for handling 64-bit overflow and carry */
627         cmpq $(0xffffffffffffffff - 16), %rax;
628         ja .Lhandle_ctr_carry;
629
630         /* construct IVs */
631         vpsubq RTMP2, RTMP0, RTMP0; /* +3 ; +2 */
632         vpshufb RTMP3, RTMP0, RA1;
633         vpsubq RTMP2, RTMP0, RTMP0; /* +5 ; +4 */
634         vpshufb RTMP3, RTMP0, RA2;
635         vpsubq RTMP2, RTMP0, RTMP0; /* +7 ; +6 */
636         vpshufb RTMP3, RTMP0, RA3;
637         vpsubq RTMP2, RTMP0, RTMP0; /* +9 ; +8 */
638         vpshufb RTMP3, RTMP0, RB0;
639         vpsubq RTMP2, RTMP0, RTMP0; /* +11 ; +10 */
640         vpshufb RTMP3, RTMP0, RB1;
641         vpsubq RTMP2, RTMP0, RTMP0; /* +13 ; +12 */
642         vpshufb RTMP3, RTMP0, RB2;
643         vpsubq RTMP2, RTMP0, RTMP0; /* +15 ; +14 */
644         vpshufb RTMP3, RTMP0, RB3;
645         vpsubq RTMP2, RTMP0, RTMP0; /* +16 */
646         vpshufb RTMP3x, RTMP0x, RTMP0x;
647
648         jmp .Lctr_carry_done;
649
650 .Lhandle_ctr_carry:
651         /* construct IVs */
652         inc_le128(RTMP0, RNOT, RTMP1);
653         inc_le128(RTMP0, RNOT, RTMP1);
654         vpshufb RTMP3, RTMP0, RA1; /* +3 ; +2 */
655         inc_le128(RTMP0, RNOT, RTMP1);
656         inc_le128(RTMP0, RNOT, RTMP1);
657         vpshufb RTMP3, RTMP0, RA2; /* +5 ; +4 */
658         inc_le128(RTMP0, RNOT, RTMP1);
659         inc_le128(RTMP0, RNOT, RTMP1);
660         vpshufb RTMP3, RTMP0, RA3; /* +7 ; +6 */
661         inc_le128(RTMP0, RNOT, RTMP1);
662         inc_le128(RTMP0, RNOT, RTMP1);
663         vpshufb RTMP3, RTMP0, RB0; /* +9 ; +8 */
664         inc_le128(RTMP0, RNOT, RTMP1);
665         inc_le128(RTMP0, RNOT, RTMP1);
666         vpshufb RTMP3, RTMP0, RB1; /* +11 ; +10 */
667         inc_le128(RTMP0, RNOT, RTMP1);
668         inc_le128(RTMP0, RNOT, RTMP1);
669         vpshufb RTMP3, RTMP0, RB2; /* +13 ; +12 */
670         inc_le128(RTMP0, RNOT, RTMP1);
671         inc_le128(RTMP0, RNOT, RTMP1);
672         vpshufb RTMP3, RTMP0, RB3; /* +15 ; +14 */
673         inc_le128(RTMP0, RNOT, RTMP1);
674         vextracti128 $1, RTMP0, RTMP0x;
675         vpshufb RTMP3x, RTMP0x, RTMP0x; /* +16 */
676
677 .align 4
678 .Lctr_carry_done:
679         /* store new IV */
680         vmovdqu RTMP0x, (%rcx);
681
682         call __serpent_enc_blk16;
683
684         vpxor (0 * 32)(%rdx), RA4, RA4;
685         vpxor (1 * 32)(%rdx), RA1, RA1;
686         vpxor (2 * 32)(%rdx), RA2, RA2;
687         vpxor (3 * 32)(%rdx), RA0, RA0;
688         vpxor (4 * 32)(%rdx), RB4, RB4;
689         vpxor (5 * 32)(%rdx), RB1, RB1;
690         vpxor (6 * 32)(%rdx), RB2, RB2;
691         vpxor (7 * 32)(%rdx), RB0, RB0;
692
693         vmovdqu RA4, (0 * 32)(%rsi);
694         vmovdqu RA1, (1 * 32)(%rsi);
695         vmovdqu RA2, (2 * 32)(%rsi);
696         vmovdqu RA0, (3 * 32)(%rsi);
697         vmovdqu RB4, (4 * 32)(%rsi);
698         vmovdqu RB1, (5 * 32)(%rsi);
699         vmovdqu RB2, (6 * 32)(%rsi);
700         vmovdqu RB0, (7 * 32)(%rsi);
701
702         vzeroall;
703
704         ret
705 ELF(.size _gcry_serpent_avx2_ctr_enc,.-_gcry_serpent_avx2_ctr_enc;)
706
707 .align 8
708 .globl _gcry_serpent_avx2_cbc_dec
709 ELF(.type   _gcry_serpent_avx2_cbc_dec,@function;)
710 _gcry_serpent_avx2_cbc_dec:
711         /* input:
712          *      %rdi: ctx, CTX
713          *      %rsi: dst (16 blocks)
714          *      %rdx: src (16 blocks)
715          *      %rcx: iv
716          */
717
718         vzeroupper;
719
720         vmovdqu (0 * 32)(%rdx), RA0;
721         vmovdqu (1 * 32)(%rdx), RA1;
722         vmovdqu (2 * 32)(%rdx), RA2;
723         vmovdqu (3 * 32)(%rdx), RA3;
724         vmovdqu (4 * 32)(%rdx), RB0;
725         vmovdqu (5 * 32)(%rdx), RB1;
726         vmovdqu (6 * 32)(%rdx), RB2;
727         vmovdqu (7 * 32)(%rdx), RB3;
728
729         call __serpent_dec_blk16;
730
731         vmovdqu (%rcx), RNOTx;
732         vinserti128 $1, (%rdx), RNOT, RNOT;
733         vpxor RNOT, RA0, RA0;
734         vpxor (0 * 32 + 16)(%rdx), RA1, RA1;
735         vpxor (1 * 32 + 16)(%rdx), RA2, RA2;
736         vpxor (2 * 32 + 16)(%rdx), RA3, RA3;
737         vpxor (3 * 32 + 16)(%rdx), RB0, RB0;
738         vpxor (4 * 32 + 16)(%rdx), RB1, RB1;
739         vpxor (5 * 32 + 16)(%rdx), RB2, RB2;
740         vpxor (6 * 32 + 16)(%rdx), RB3, RB3;
741         vmovdqu (7 * 32 + 16)(%rdx), RNOTx;
742         vmovdqu RNOTx, (%rcx); /* store new IV */
743
744         vmovdqu RA0, (0 * 32)(%rsi);
745         vmovdqu RA1, (1 * 32)(%rsi);
746         vmovdqu RA2, (2 * 32)(%rsi);
747         vmovdqu RA3, (3 * 32)(%rsi);
748         vmovdqu RB0, (4 * 32)(%rsi);
749         vmovdqu RB1, (5 * 32)(%rsi);
750         vmovdqu RB2, (6 * 32)(%rsi);
751         vmovdqu RB3, (7 * 32)(%rsi);
752
753         vzeroall;
754
755         ret
756 ELF(.size _gcry_serpent_avx2_cbc_dec,.-_gcry_serpent_avx2_cbc_dec;)
757
758 .align 8
759 .globl _gcry_serpent_avx2_cfb_dec
760 ELF(.type   _gcry_serpent_avx2_cfb_dec,@function;)
761 _gcry_serpent_avx2_cfb_dec:
762         /* input:
763          *      %rdi: ctx, CTX
764          *      %rsi: dst (16 blocks)
765          *      %rdx: src (16 blocks)
766          *      %rcx: iv
767          */
768
769         vzeroupper;
770
771         /* Load input */
772         vmovdqu (%rcx), RNOTx;
773         vinserti128 $1, (%rdx), RNOT, RA0;
774         vmovdqu (0 * 32 + 16)(%rdx), RA1;
775         vmovdqu (1 * 32 + 16)(%rdx), RA2;
776         vmovdqu (2 * 32 + 16)(%rdx), RA3;
777         vmovdqu (3 * 32 + 16)(%rdx), RB0;
778         vmovdqu (4 * 32 + 16)(%rdx), RB1;
779         vmovdqu (5 * 32 + 16)(%rdx), RB2;
780         vmovdqu (6 * 32 + 16)(%rdx), RB3;
781
782         /* Update IV */
783         vmovdqu (7 * 32 + 16)(%rdx), RNOTx;
784         vmovdqu RNOTx, (%rcx);
785
786         call __serpent_enc_blk16;
787
788         vpxor (0 * 32)(%rdx), RA4, RA4;
789         vpxor (1 * 32)(%rdx), RA1, RA1;
790         vpxor (2 * 32)(%rdx), RA2, RA2;
791         vpxor (3 * 32)(%rdx), RA0, RA0;
792         vpxor (4 * 32)(%rdx), RB4, RB4;
793         vpxor (5 * 32)(%rdx), RB1, RB1;
794         vpxor (6 * 32)(%rdx), RB2, RB2;
795         vpxor (7 * 32)(%rdx), RB0, RB0;
796
797         vmovdqu RA4, (0 * 32)(%rsi);
798         vmovdqu RA1, (1 * 32)(%rsi);
799         vmovdqu RA2, (2 * 32)(%rsi);
800         vmovdqu RA0, (3 * 32)(%rsi);
801         vmovdqu RB4, (4 * 32)(%rsi);
802         vmovdqu RB1, (5 * 32)(%rsi);
803         vmovdqu RB2, (6 * 32)(%rsi);
804         vmovdqu RB0, (7 * 32)(%rsi);
805
806         vzeroall;
807
808         ret
809 ELF(.size _gcry_serpent_avx2_cfb_dec,.-_gcry_serpent_avx2_cfb_dec;)
810
811 .align 8
812 .globl _gcry_serpent_avx2_ocb_enc
813 ELF(.type _gcry_serpent_avx2_ocb_enc,@function;)
814
815 _gcry_serpent_avx2_ocb_enc:
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
825         vzeroupper;
826
827         subq $(4 * 8), %rsp;
828
829         movq %r10, (0 * 8)(%rsp);
830         movq %r11, (1 * 8)(%rsp);
831         movq %r12, (2 * 8)(%rsp);
832         movq %r13, (3 * 8)(%rsp);
833
834         vmovdqu (%rcx), RTMP0x;
835         vmovdqu (%r8), RTMP1x;
836
837         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
838         /* Checksum_i = Checksum_{i-1} xor P_i  */
839         /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
840
841 #define OCB_INPUT(n, l0reg, l1reg, yreg) \
842           vmovdqu (n * 32)(%rdx), yreg; \
843           vpxor (l0reg), RTMP0x, RNOTx; \
844           vpxor (l1reg), RNOTx, RTMP0x; \
845           vinserti128 $1, RTMP0x, RNOT, RNOT; \
846           vpxor yreg, RTMP1, RTMP1; \
847           vpxor yreg, RNOT, yreg; \
848           vmovdqu RNOT, (n * 32)(%rsi);
849
850         movq (0 * 8)(%r9), %r10;
851         movq (1 * 8)(%r9), %r11;
852         movq (2 * 8)(%r9), %r12;
853         movq (3 * 8)(%r9), %r13;
854         OCB_INPUT(0, %r10, %r11, RA0);
855         OCB_INPUT(1, %r12, %r13, RA1);
856         movq (4 * 8)(%r9), %r10;
857         movq (5 * 8)(%r9), %r11;
858         movq (6 * 8)(%r9), %r12;
859         movq (7 * 8)(%r9), %r13;
860         OCB_INPUT(2, %r10, %r11, RA2);
861         OCB_INPUT(3, %r12, %r13, RA3);
862         movq (8 * 8)(%r9), %r10;
863         movq (9 * 8)(%r9), %r11;
864         movq (10 * 8)(%r9), %r12;
865         movq (11 * 8)(%r9), %r13;
866         OCB_INPUT(4, %r10, %r11, RB0);
867         OCB_INPUT(5, %r12, %r13, RB1);
868         movq (12 * 8)(%r9), %r10;
869         movq (13 * 8)(%r9), %r11;
870         movq (14 * 8)(%r9), %r12;
871         movq (15 * 8)(%r9), %r13;
872         OCB_INPUT(6, %r10, %r11, RB2);
873         OCB_INPUT(7, %r12, %r13, RB3);
874 #undef OCB_INPUT
875
876         vextracti128 $1, RTMP1, RNOTx;
877         vmovdqu RTMP0x, (%rcx);
878         vpxor RNOTx, RTMP1x, RTMP1x;
879         vmovdqu RTMP1x, (%r8);
880
881         movq (0 * 8)(%rsp), %r10;
882         movq (1 * 8)(%rsp), %r11;
883         movq (2 * 8)(%rsp), %r12;
884         movq (3 * 8)(%rsp), %r13;
885
886         call __serpent_enc_blk16;
887
888         addq $(4 * 8), %rsp;
889
890         vpxor (0 * 32)(%rsi), RA4, RA4;
891         vpxor (1 * 32)(%rsi), RA1, RA1;
892         vpxor (2 * 32)(%rsi), RA2, RA2;
893         vpxor (3 * 32)(%rsi), RA0, RA0;
894         vpxor (4 * 32)(%rsi), RB4, RB4;
895         vpxor (5 * 32)(%rsi), RB1, RB1;
896         vpxor (6 * 32)(%rsi), RB2, RB2;
897         vpxor (7 * 32)(%rsi), RB0, RB0;
898
899         vmovdqu RA4, (0 * 32)(%rsi);
900         vmovdqu RA1, (1 * 32)(%rsi);
901         vmovdqu RA2, (2 * 32)(%rsi);
902         vmovdqu RA0, (3 * 32)(%rsi);
903         vmovdqu RB4, (4 * 32)(%rsi);
904         vmovdqu RB1, (5 * 32)(%rsi);
905         vmovdqu RB2, (6 * 32)(%rsi);
906         vmovdqu RB0, (7 * 32)(%rsi);
907
908         vzeroall;
909
910         ret;
911 ELF(.size _gcry_serpent_avx2_ocb_enc,.-_gcry_serpent_avx2_ocb_enc;)
912
913 .align 8
914 .globl _gcry_serpent_avx2_ocb_dec
915 ELF(.type _gcry_serpent_avx2_ocb_dec,@function;)
916
917 _gcry_serpent_avx2_ocb_dec:
918         /* input:
919          *      %rdi: ctx, CTX
920          *      %rsi: dst (16 blocks)
921          *      %rdx: src (16 blocks)
922          *      %rcx: offset
923          *      %r8 : checksum
924          *      %r9 : L pointers (void *L[16])
925          */
926
927         vzeroupper;
928
929         subq $(4 * 8), %rsp;
930
931         movq %r10, (0 * 8)(%rsp);
932         movq %r11, (1 * 8)(%rsp);
933         movq %r12, (2 * 8)(%rsp);
934         movq %r13, (3 * 8)(%rsp);
935
936         vmovdqu (%rcx), RTMP0x;
937
938         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
939         /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
940
941 #define OCB_INPUT(n, l0reg, l1reg, yreg) \
942           vmovdqu (n * 32)(%rdx), yreg; \
943           vpxor (l0reg), RTMP0x, RNOTx; \
944           vpxor (l1reg), RNOTx, RTMP0x; \
945           vinserti128 $1, RTMP0x, RNOT, RNOT; \
946           vpxor yreg, RNOT, yreg; \
947           vmovdqu RNOT, (n * 32)(%rsi);
948
949         movq (0 * 8)(%r9), %r10;
950         movq (1 * 8)(%r9), %r11;
951         movq (2 * 8)(%r9), %r12;
952         movq (3 * 8)(%r9), %r13;
953         OCB_INPUT(0, %r10, %r11, RA0);
954         OCB_INPUT(1, %r12, %r13, RA1);
955         movq (4 * 8)(%r9), %r10;
956         movq (5 * 8)(%r9), %r11;
957         movq (6 * 8)(%r9), %r12;
958         movq (7 * 8)(%r9), %r13;
959         OCB_INPUT(2, %r10, %r11, RA2);
960         OCB_INPUT(3, %r12, %r13, RA3);
961         movq (8 * 8)(%r9), %r10;
962         movq (9 * 8)(%r9), %r11;
963         movq (10 * 8)(%r9), %r12;
964         movq (11 * 8)(%r9), %r13;
965         OCB_INPUT(4, %r10, %r11, RB0);
966         OCB_INPUT(5, %r12, %r13, RB1);
967         movq (12 * 8)(%r9), %r10;
968         movq (13 * 8)(%r9), %r11;
969         movq (14 * 8)(%r9), %r12;
970         movq (15 * 8)(%r9), %r13;
971         OCB_INPUT(6, %r10, %r11, RB2);
972         OCB_INPUT(7, %r12, %r13, RB3);
973 #undef OCB_INPUT
974
975         vmovdqu RTMP0x, (%rcx);
976
977         movq (0 * 8)(%rsp), %r10;
978         movq (1 * 8)(%rsp), %r11;
979         movq (2 * 8)(%rsp), %r12;
980         movq (3 * 8)(%rsp), %r13;
981
982         call __serpent_dec_blk16;
983
984         addq $(4 * 8), %rsp;
985
986         vmovdqu (%r8), RTMP1x;
987
988         vpxor (0 * 32)(%rsi), RA0, RA0;
989         vpxor (1 * 32)(%rsi), RA1, RA1;
990         vpxor (2 * 32)(%rsi), RA2, RA2;
991         vpxor (3 * 32)(%rsi), RA3, RA3;
992         vpxor (4 * 32)(%rsi), RB0, RB0;
993         vpxor (5 * 32)(%rsi), RB1, RB1;
994         vpxor (6 * 32)(%rsi), RB2, RB2;
995         vpxor (7 * 32)(%rsi), RB3, RB3;
996
997         /* Checksum_i = Checksum_{i-1} xor P_i  */
998
999         vmovdqu RA0, (0 * 32)(%rsi);
1000         vpxor RA0, RTMP1, RTMP1;
1001         vmovdqu RA1, (1 * 32)(%rsi);
1002         vpxor RA1, RTMP1, RTMP1;
1003         vmovdqu RA2, (2 * 32)(%rsi);
1004         vpxor RA2, RTMP1, RTMP1;
1005         vmovdqu RA3, (3 * 32)(%rsi);
1006         vpxor RA3, RTMP1, RTMP1;
1007         vmovdqu RB0, (4 * 32)(%rsi);
1008         vpxor RB0, RTMP1, RTMP1;
1009         vmovdqu RB1, (5 * 32)(%rsi);
1010         vpxor RB1, RTMP1, RTMP1;
1011         vmovdqu RB2, (6 * 32)(%rsi);
1012         vpxor RB2, RTMP1, RTMP1;
1013         vmovdqu RB3, (7 * 32)(%rsi);
1014         vpxor RB3, RTMP1, RTMP1;
1015
1016         vextracti128 $1, RTMP1, RNOTx;
1017         vpxor RNOTx, RTMP1x, RTMP1x;
1018         vmovdqu RTMP1x, (%r8);
1019
1020         vzeroall;
1021
1022         ret;
1023 ELF(.size _gcry_serpent_avx2_ocb_dec,.-_gcry_serpent_avx2_ocb_dec;)
1024
1025 .align 8
1026 .globl _gcry_serpent_avx2_ocb_auth
1027 ELF(.type _gcry_serpent_avx2_ocb_auth,@function;)
1028
1029 _gcry_serpent_avx2_ocb_auth:
1030         /* input:
1031          *      %rdi: ctx, CTX
1032          *      %rsi: abuf (16 blocks)
1033          *      %rdx: offset
1034          *      %rcx: checksum
1035          *      %r8 : L pointers (void *L[16])
1036          */
1037
1038         vzeroupper;
1039
1040         subq $(4 * 8), %rsp;
1041
1042         movq %r10, (0 * 8)(%rsp);
1043         movq %r11, (1 * 8)(%rsp);
1044         movq %r12, (2 * 8)(%rsp);
1045         movq %r13, (3 * 8)(%rsp);
1046
1047         vmovdqu (%rdx), RTMP0x;
1048
1049         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1050         /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
1051
1052 #define OCB_INPUT(n, l0reg, l1reg, yreg) \
1053           vmovdqu (n * 32)(%rsi), yreg; \
1054           vpxor (l0reg), RTMP0x, RNOTx; \
1055           vpxor (l1reg), RNOTx, RTMP0x; \
1056           vinserti128 $1, RTMP0x, RNOT, RNOT; \
1057           vpxor yreg, RNOT, yreg;
1058
1059         movq (0 * 8)(%r8), %r10;
1060         movq (1 * 8)(%r8), %r11;
1061         movq (2 * 8)(%r8), %r12;
1062         movq (3 * 8)(%r8), %r13;
1063         OCB_INPUT(0, %r10, %r11, RA0);
1064         OCB_INPUT(1, %r12, %r13, RA1);
1065         movq (4 * 8)(%r8), %r10;
1066         movq (5 * 8)(%r8), %r11;
1067         movq (6 * 8)(%r8), %r12;
1068         movq (7 * 8)(%r8), %r13;
1069         OCB_INPUT(2, %r10, %r11, RA2);
1070         OCB_INPUT(3, %r12, %r13, RA3);
1071         movq (8 * 8)(%r8), %r10;
1072         movq (9 * 8)(%r8), %r11;
1073         movq (10 * 8)(%r8), %r12;
1074         movq (11 * 8)(%r8), %r13;
1075         OCB_INPUT(4, %r10, %r11, RB0);
1076         OCB_INPUT(5, %r12, %r13, RB1);
1077         movq (12 * 8)(%r8), %r10;
1078         movq (13 * 8)(%r8), %r11;
1079         movq (14 * 8)(%r8), %r12;
1080         movq (15 * 8)(%r8), %r13;
1081         OCB_INPUT(6, %r10, %r11, RB2);
1082         OCB_INPUT(7, %r12, %r13, RB3);
1083 #undef OCB_INPUT
1084
1085         vmovdqu RTMP0x, (%rdx);
1086
1087         movq (0 * 8)(%rsp), %r10;
1088         movq (1 * 8)(%rsp), %r11;
1089         movq (2 * 8)(%rsp), %r12;
1090         movq (3 * 8)(%rsp), %r13;
1091
1092         call __serpent_enc_blk16;
1093
1094         addq $(4 * 8), %rsp;
1095
1096         vpxor RA4, RB4, RA4;
1097         vpxor RA1, RB1, RA1;
1098         vpxor RA2, RB2, RA2;
1099         vpxor RA0, RB0, RA0;
1100
1101         vpxor RA4, RA1, RA1;
1102         vpxor RA2, RA0, RA0;
1103
1104         vpxor RA1, RA0, RTMP1;
1105
1106         vextracti128 $1, RTMP1, RNOTx;
1107         vpxor (%rcx), RTMP1x, RTMP1x;
1108         vpxor RNOTx, RTMP1x, RTMP1x;
1109         vmovdqu RTMP1x, (%rcx);
1110
1111         vzeroall;
1112
1113         ret;
1114 ELF(.size _gcry_serpent_avx2_ocb_auth,.-_gcry_serpent_avx2_ocb_auth;)
1115
1116 .align 16
1117
1118 /* For CTR-mode IV byteswap */
1119 .Lbswap128_mask:
1120         .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
1121
1122 #endif /*defined(USE_SERPENT) && defined(ENABLE_AVX2_SUPPORT)*/
1123 #endif /*__x86_64*/