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