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