doc: Fix typo.
[libgcrypt.git] / cipher / des-amd64.S
1 /* des-amd64.S  -  AMD64 assembly implementation of 3DES cipher
2  *
3  * Copyright (C) 2014 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(USE_DES) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
24     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
25
26 #ifdef __PIC__
27 #  define RIP (%rip)
28 #else
29 #  define RIP
30 #endif
31
32 #ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
33 # define ELF(...) __VA_ARGS__
34 #else
35 # define ELF(...) /*_*/
36 #endif
37
38 .text
39
40 #define s1 0
41 #define s2 ((s1) + (64*8))
42 #define s3 ((s2) + (64*8))
43 #define s4 ((s3) + (64*8))
44 #define s5 ((s4) + (64*8))
45 #define s6 ((s5) + (64*8))
46 #define s7 ((s6) + (64*8))
47 #define s8 ((s7) + (64*8))
48
49 /* register macros */
50 #define CTX %rdi
51 #define SBOXES %rbp
52
53 #define RL0 %r8
54 #define RL1 %r9
55 #define RL2 %r10
56
57 #define RL0d %r8d
58 #define RL1d %r9d
59 #define RL2d %r10d
60
61 #define RR0 %r11
62 #define RR1 %r12
63 #define RR2 %r13
64
65 #define RR0d %r11d
66 #define RR1d %r12d
67 #define RR2d %r13d
68
69 #define RW0 %rax
70 #define RW1 %rbx
71 #define RW2 %rcx
72
73 #define RW0d %eax
74 #define RW1d %ebx
75 #define RW2d %ecx
76
77 #define RW0bl %al
78 #define RW1bl %bl
79 #define RW2bl %cl
80
81 #define RW0bh %ah
82 #define RW1bh %bh
83 #define RW2bh %ch
84
85 #define RT0 %r15
86 #define RT1 %rsi
87 #define RT2 %r14
88 #define RT3 %rdx
89
90 #define RT0d %r15d
91 #define RT1d %esi
92 #define RT2d %r14d
93 #define RT3d %edx
94
95 /***********************************************************************
96  * 1-way 3DES
97  ***********************************************************************/
98 #define do_permutation(a, b, offset, mask) \
99         movl a, RT0d; \
100         shrl $(offset), RT0d; \
101         xorl b, RT0d; \
102         andl $(mask), RT0d; \
103         xorl RT0d, b; \
104         shll $(offset), RT0d; \
105         xorl RT0d, a;
106
107 #define expand_to_64bits(val, mask) \
108         movl val##d, RT0d; \
109         rorl $4, RT0d; \
110         shlq $32, RT0; \
111         orq RT0, val; \
112         andq mask, val;
113
114 #define compress_to_64bits(val) \
115         movq val, RT0; \
116         shrq $32, RT0; \
117         roll $4, RT0d; \
118         orl RT0d, val##d;
119
120 #define initial_permutation(left, right) \
121         do_permutation(left##d, right##d,  4, 0x0f0f0f0f); \
122         do_permutation(left##d, right##d, 16, 0x0000ffff); \
123         do_permutation(right##d, left##d,  2, 0x33333333); \
124         do_permutation(right##d, left##d,  8, 0x00ff00ff); \
125         movabs $0x3f3f3f3f3f3f3f3f, RT3; \
126         movl left##d, RW0d; \
127         roll $1, right##d; \
128         xorl right##d, RW0d; \
129         andl $0xaaaaaaaa, RW0d; \
130         xorl RW0d, left##d; \
131         xorl RW0d, right##d; \
132         roll $1, left##d; \
133         expand_to_64bits(right, RT3); \
134         expand_to_64bits(left, RT3);
135
136 #define final_permutation(left, right) \
137         compress_to_64bits(right); \
138         compress_to_64bits(left); \
139         movl right##d, RW0d; \
140         rorl $1, left##d; \
141         xorl left##d, RW0d; \
142         andl $0xaaaaaaaa, RW0d; \
143         xorl RW0d, right##d; \
144         xorl RW0d, left##d; \
145         rorl $1, right##d; \
146         do_permutation(right##d, left##d,  8, 0x00ff00ff); \
147         do_permutation(right##d, left##d,  2, 0x33333333); \
148         do_permutation(left##d, right##d, 16, 0x0000ffff); \
149         do_permutation(left##d, right##d,  4, 0x0f0f0f0f);
150
151 #define round1(n, from, to, load_next_key) \
152         xorq from, RW0; \
153         \
154         movzbl RW0bl, RT0d; \
155         movzbl RW0bh, RT1d; \
156         shrq $16, RW0; \
157         movzbl RW0bl, RT2d; \
158         movzbl RW0bh, RT3d; \
159         shrq $16, RW0; \
160         movq s8(SBOXES, RT0, 8), RT0; \
161         xorq s6(SBOXES, RT1, 8), to; \
162         movzbl RW0bl, RL1d; \
163         movzbl RW0bh, RT1d; \
164         shrl $16, RW0d; \
165         xorq s4(SBOXES, RT2, 8), RT0; \
166         xorq s2(SBOXES, RT3, 8), to; \
167         movzbl RW0bl, RT2d; \
168         movzbl RW0bh, RT3d; \
169         xorq s7(SBOXES, RL1, 8), RT0; \
170         xorq s5(SBOXES, RT1, 8), to; \
171         xorq s3(SBOXES, RT2, 8), RT0; \
172         load_next_key(n, RW0); \
173         xorq RT0, to; \
174         xorq s1(SBOXES, RT3, 8), to; \
175
176 #define load_next_key(n, RWx) \
177         movq (((n) + 1) * 8)(CTX), RWx;
178
179 #define dummy2(a, b) /*_*/
180
181 #define read_block(io, left, right) \
182         movl    (io), left##d; \
183         movl   4(io), right##d; \
184         bswapl left##d; \
185         bswapl right##d;
186
187 #define write_block(io, left, right) \
188         bswapl left##d; \
189         bswapl right##d; \
190         movl   left##d,   (io); \
191         movl   right##d, 4(io);
192
193 .align 8
194 .globl _gcry_3des_amd64_crypt_block
195 ELF(.type  _gcry_3des_amd64_crypt_block,@function;)
196
197 _gcry_3des_amd64_crypt_block:
198         /* input:
199          *      %rdi: round keys, CTX
200          *      %rsi: dst
201          *      %rdx: src
202          */
203         pushq %rbp;
204         pushq %rbx;
205         pushq %r12;
206         pushq %r13;
207         pushq %r14;
208         pushq %r15;
209         pushq %rsi; /*dst*/
210
211         leaq .L_s1 RIP, SBOXES;
212
213         read_block(%rdx, RL0, RR0);
214         initial_permutation(RL0, RR0);
215
216         movq (CTX), RW0;
217
218         round1(0, RR0, RL0, load_next_key);
219         round1(1, RL0, RR0, load_next_key);
220         round1(2, RR0, RL0, load_next_key);
221         round1(3, RL0, RR0, load_next_key);
222         round1(4, RR0, RL0, load_next_key);
223         round1(5, RL0, RR0, load_next_key);
224         round1(6, RR0, RL0, load_next_key);
225         round1(7, RL0, RR0, load_next_key);
226         round1(8, RR0, RL0, load_next_key);
227         round1(9, RL0, RR0, load_next_key);
228         round1(10, RR0, RL0, load_next_key);
229         round1(11, RL0, RR0, load_next_key);
230         round1(12, RR0, RL0, load_next_key);
231         round1(13, RL0, RR0, load_next_key);
232         round1(14, RR0, RL0, load_next_key);
233         round1(15, RL0, RR0, load_next_key);
234
235         round1(16+0, RL0, RR0, load_next_key);
236         round1(16+1, RR0, RL0, load_next_key);
237         round1(16+2, RL0, RR0, load_next_key);
238         round1(16+3, RR0, RL0, load_next_key);
239         round1(16+4, RL0, RR0, load_next_key);
240         round1(16+5, RR0, RL0, load_next_key);
241         round1(16+6, RL0, RR0, load_next_key);
242         round1(16+7, RR0, RL0, load_next_key);
243         round1(16+8, RL0, RR0, load_next_key);
244         round1(16+9, RR0, RL0, load_next_key);
245         round1(16+10, RL0, RR0, load_next_key);
246         round1(16+11, RR0, RL0, load_next_key);
247         round1(16+12, RL0, RR0, load_next_key);
248         round1(16+13, RR0, RL0, load_next_key);
249         round1(16+14, RL0, RR0, load_next_key);
250         round1(16+15, RR0, RL0, load_next_key);
251
252         round1(32+0, RR0, RL0, load_next_key);
253         round1(32+1, RL0, RR0, load_next_key);
254         round1(32+2, RR0, RL0, load_next_key);
255         round1(32+3, RL0, RR0, load_next_key);
256         round1(32+4, RR0, RL0, load_next_key);
257         round1(32+5, RL0, RR0, load_next_key);
258         round1(32+6, RR0, RL0, load_next_key);
259         round1(32+7, RL0, RR0, load_next_key);
260         round1(32+8, RR0, RL0, load_next_key);
261         round1(32+9, RL0, RR0, load_next_key);
262         round1(32+10, RR0, RL0, load_next_key);
263         round1(32+11, RL0, RR0, load_next_key);
264         round1(32+12, RR0, RL0, load_next_key);
265         round1(32+13, RL0, RR0, load_next_key);
266         round1(32+14, RR0, RL0, load_next_key);
267         round1(32+15, RL0, RR0, dummy2);
268
269         popq RW2; /*dst*/
270         final_permutation(RR0, RL0);
271         write_block(RW2, RR0, RL0);
272
273         popq %r15;
274         popq %r14;
275         popq %r13;
276         popq %r12;
277         popq %rbx;
278         popq %rbp;
279
280         ret;
281 ELF(.size _gcry_3des_amd64_crypt_block,.-_gcry_3des_amd64_crypt_block;)
282
283 /***********************************************************************
284  * 3-way 3DES
285  ***********************************************************************/
286 #define expand_to_64bits(val, mask) \
287         movl val##d, RT0d; \
288         rorl $4, RT0d; \
289         shlq $32, RT0; \
290         orq RT0, val; \
291         andq mask, val;
292
293 #define compress_to_64bits(val) \
294         movq val, RT0; \
295         shrq $32, RT0; \
296         roll $4, RT0d; \
297         orl RT0d, val##d;
298
299 #define initial_permutation3(left, right) \
300         do_permutation(left##0d, right##0d,  4, 0x0f0f0f0f); \
301         do_permutation(left##0d, right##0d, 16, 0x0000ffff); \
302           do_permutation(left##1d, right##1d,  4, 0x0f0f0f0f); \
303           do_permutation(left##1d, right##1d, 16, 0x0000ffff); \
304             do_permutation(left##2d, right##2d,  4, 0x0f0f0f0f); \
305             do_permutation(left##2d, right##2d, 16, 0x0000ffff); \
306             \
307         do_permutation(right##0d, left##0d,  2, 0x33333333); \
308         do_permutation(right##0d, left##0d,  8, 0x00ff00ff); \
309           do_permutation(right##1d, left##1d,  2, 0x33333333); \
310           do_permutation(right##1d, left##1d,  8, 0x00ff00ff); \
311             do_permutation(right##2d, left##2d,  2, 0x33333333); \
312             do_permutation(right##2d, left##2d,  8, 0x00ff00ff); \
313             \
314         movabs $0x3f3f3f3f3f3f3f3f, RT3; \
315             \
316         movl left##0d, RW0d; \
317         roll $1, right##0d; \
318         xorl right##0d, RW0d; \
319         andl $0xaaaaaaaa, RW0d; \
320         xorl RW0d, left##0d; \
321         xorl RW0d, right##0d; \
322         roll $1, left##0d; \
323         expand_to_64bits(right##0, RT3); \
324         expand_to_64bits(left##0, RT3); \
325           movl left##1d, RW1d; \
326           roll $1, right##1d; \
327           xorl right##1d, RW1d; \
328           andl $0xaaaaaaaa, RW1d; \
329           xorl RW1d, left##1d; \
330           xorl RW1d, right##1d; \
331           roll $1, left##1d; \
332           expand_to_64bits(right##1, RT3); \
333           expand_to_64bits(left##1, RT3); \
334             movl left##2d, RW2d; \
335             roll $1, right##2d; \
336             xorl right##2d, RW2d; \
337             andl $0xaaaaaaaa, RW2d; \
338             xorl RW2d, left##2d; \
339             xorl RW2d, right##2d; \
340             roll $1, left##2d; \
341             expand_to_64bits(right##2, RT3); \
342             expand_to_64bits(left##2, RT3);
343
344 #define final_permutation3(left, right) \
345         compress_to_64bits(right##0); \
346         compress_to_64bits(left##0); \
347         movl right##0d, RW0d; \
348         rorl $1, left##0d; \
349         xorl left##0d, RW0d; \
350         andl $0xaaaaaaaa, RW0d; \
351         xorl RW0d, right##0d; \
352         xorl RW0d, left##0d; \
353         rorl $1, right##0d; \
354           compress_to_64bits(right##1); \
355           compress_to_64bits(left##1); \
356           movl right##1d, RW1d; \
357           rorl $1, left##1d; \
358           xorl left##1d, RW1d; \
359           andl $0xaaaaaaaa, RW1d; \
360           xorl RW1d, right##1d; \
361           xorl RW1d, left##1d; \
362           rorl $1, right##1d; \
363             compress_to_64bits(right##2); \
364             compress_to_64bits(left##2); \
365             movl right##2d, RW2d; \
366             rorl $1, left##2d; \
367             xorl left##2d, RW2d; \
368             andl $0xaaaaaaaa, RW2d; \
369             xorl RW2d, right##2d; \
370             xorl RW2d, left##2d; \
371             rorl $1, right##2d; \
372             \
373         do_permutation(right##0d, left##0d,  8, 0x00ff00ff); \
374         do_permutation(right##0d, left##0d,  2, 0x33333333); \
375           do_permutation(right##1d, left##1d,  8, 0x00ff00ff); \
376           do_permutation(right##1d, left##1d,  2, 0x33333333); \
377             do_permutation(right##2d, left##2d,  8, 0x00ff00ff); \
378             do_permutation(right##2d, left##2d,  2, 0x33333333); \
379             \
380         do_permutation(left##0d, right##0d, 16, 0x0000ffff); \
381         do_permutation(left##0d, right##0d,  4, 0x0f0f0f0f); \
382           do_permutation(left##1d, right##1d, 16, 0x0000ffff); \
383           do_permutation(left##1d, right##1d,  4, 0x0f0f0f0f); \
384             do_permutation(left##2d, right##2d, 16, 0x0000ffff); \
385             do_permutation(left##2d, right##2d,  4, 0x0f0f0f0f);
386
387 #define round3(n, from, to, load_next_key, do_movq) \
388         xorq from##0, RW0; \
389         movzbl RW0bl, RT3d; \
390         movzbl RW0bh, RT1d; \
391         shrq $16, RW0; \
392         xorq s8(SBOXES, RT3, 8), to##0; \
393         xorq s6(SBOXES, RT1, 8), to##0; \
394         movzbl RW0bl, RT3d; \
395         movzbl RW0bh, RT1d; \
396         shrq $16, RW0; \
397         xorq s4(SBOXES, RT3, 8), to##0; \
398         xorq s2(SBOXES, RT1, 8), to##0; \
399         movzbl RW0bl, RT3d; \
400         movzbl RW0bh, RT1d; \
401         shrl $16, RW0d; \
402         xorq s7(SBOXES, RT3, 8), to##0; \
403         xorq s5(SBOXES, RT1, 8), to##0; \
404         movzbl RW0bl, RT3d; \
405         movzbl RW0bh, RT1d; \
406         load_next_key(n, RW0); \
407         xorq s3(SBOXES, RT3, 8), to##0; \
408         xorq s1(SBOXES, RT1, 8), to##0; \
409                 xorq from##1, RW1; \
410                 movzbl RW1bl, RT3d; \
411                 movzbl RW1bh, RT1d; \
412                 shrq $16, RW1; \
413                 xorq s8(SBOXES, RT3, 8), to##1; \
414                 xorq s6(SBOXES, RT1, 8), to##1; \
415                 movzbl RW1bl, RT3d; \
416                 movzbl RW1bh, RT1d; \
417                 shrq $16, RW1; \
418                 xorq s4(SBOXES, RT3, 8), to##1; \
419                 xorq s2(SBOXES, RT1, 8), to##1; \
420                 movzbl RW1bl, RT3d; \
421                 movzbl RW1bh, RT1d; \
422                 shrl $16, RW1d; \
423                 xorq s7(SBOXES, RT3, 8), to##1; \
424                 xorq s5(SBOXES, RT1, 8), to##1; \
425                 movzbl RW1bl, RT3d; \
426                 movzbl RW1bh, RT1d; \
427                 do_movq(RW0, RW1); \
428                 xorq s3(SBOXES, RT3, 8), to##1; \
429                 xorq s1(SBOXES, RT1, 8), to##1; \
430                         xorq from##2, RW2; \
431                         movzbl RW2bl, RT3d; \
432                         movzbl RW2bh, RT1d; \
433                         shrq $16, RW2; \
434                         xorq s8(SBOXES, RT3, 8), to##2; \
435                         xorq s6(SBOXES, RT1, 8), to##2; \
436                         movzbl RW2bl, RT3d; \
437                         movzbl RW2bh, RT1d; \
438                         shrq $16, RW2; \
439                         xorq s4(SBOXES, RT3, 8), to##2; \
440                         xorq s2(SBOXES, RT1, 8), to##2; \
441                         movzbl RW2bl, RT3d; \
442                         movzbl RW2bh, RT1d; \
443                         shrl $16, RW2d; \
444                         xorq s7(SBOXES, RT3, 8), to##2; \
445                         xorq s5(SBOXES, RT1, 8), to##2; \
446                         movzbl RW2bl, RT3d; \
447                         movzbl RW2bh, RT1d; \
448                         do_movq(RW0, RW2); \
449                         xorq s3(SBOXES, RT3, 8), to##2; \
450                         xorq s1(SBOXES, RT1, 8), to##2;
451
452 #define __movq(src, dst) \
453         movq src, dst;
454
455 #define read_block(io, left, right) \
456         movl    (io), left##d; \
457         movl   4(io), right##d; \
458         bswapl left##d; \
459         bswapl right##d;
460
461 #define write_block(io, left, right) \
462         bswapl left##d; \
463         bswapl right##d; \
464         movl   left##d,   (io); \
465         movl   right##d, 4(io);
466
467 .align 8
468 ELF(.type  _gcry_3des_amd64_crypt_blk3,@function;)
469 _gcry_3des_amd64_crypt_blk3:
470         /* input:
471          *  %rdi: round keys, CTX
472          *  RL0d, RR0d, RL1d, RR1d, RL2d, RR2d: 3 input blocks
473          *  RR0d, RL0d, RR1d, RL1d, RR2d, RL2d: 3 output blocks
474          */
475
476         leaq .L_s1 RIP, SBOXES;
477
478         initial_permutation3(RL, RR);
479
480         movq 0(CTX), RW0;
481         movq RW0, RW1;
482         movq RW0, RW2;
483
484         round3(0, RR, RL, load_next_key, __movq);
485         round3(1, RL, RR, load_next_key, __movq);
486         round3(2, RR, RL, load_next_key, __movq);
487         round3(3, RL, RR, load_next_key, __movq);
488         round3(4, RR, RL, load_next_key, __movq);
489         round3(5, RL, RR, load_next_key, __movq);
490         round3(6, RR, RL, load_next_key, __movq);
491         round3(7, RL, RR, load_next_key, __movq);
492         round3(8, RR, RL, load_next_key, __movq);
493         round3(9, RL, RR, load_next_key, __movq);
494         round3(10, RR, RL, load_next_key, __movq);
495         round3(11, RL, RR, load_next_key, __movq);
496         round3(12, RR, RL, load_next_key, __movq);
497         round3(13, RL, RR, load_next_key, __movq);
498         round3(14, RR, RL, load_next_key, __movq);
499         round3(15, RL, RR, load_next_key, __movq);
500
501         round3(16+0, RL, RR, load_next_key, __movq);
502         round3(16+1, RR, RL, load_next_key, __movq);
503         round3(16+2, RL, RR, load_next_key, __movq);
504         round3(16+3, RR, RL, load_next_key, __movq);
505         round3(16+4, RL, RR, load_next_key, __movq);
506         round3(16+5, RR, RL, load_next_key, __movq);
507         round3(16+6, RL, RR, load_next_key, __movq);
508         round3(16+7, RR, RL, load_next_key, __movq);
509         round3(16+8, RL, RR, load_next_key, __movq);
510         round3(16+9, RR, RL, load_next_key, __movq);
511         round3(16+10, RL, RR, load_next_key, __movq);
512         round3(16+11, RR, RL, load_next_key, __movq);
513         round3(16+12, RL, RR, load_next_key, __movq);
514         round3(16+13, RR, RL, load_next_key, __movq);
515         round3(16+14, RL, RR, load_next_key, __movq);
516         round3(16+15, RR, RL, load_next_key, __movq);
517
518         round3(32+0, RR, RL, load_next_key, __movq);
519         round3(32+1, RL, RR, load_next_key, __movq);
520         round3(32+2, RR, RL, load_next_key, __movq);
521         round3(32+3, RL, RR, load_next_key, __movq);
522         round3(32+4, RR, RL, load_next_key, __movq);
523         round3(32+5, RL, RR, load_next_key, __movq);
524         round3(32+6, RR, RL, load_next_key, __movq);
525         round3(32+7, RL, RR, load_next_key, __movq);
526         round3(32+8, RR, RL, load_next_key, __movq);
527         round3(32+9, RL, RR, load_next_key, __movq);
528         round3(32+10, RR, RL, load_next_key, __movq);
529         round3(32+11, RL, RR, load_next_key, __movq);
530         round3(32+12, RR, RL, load_next_key, __movq);
531         round3(32+13, RL, RR, load_next_key, __movq);
532         round3(32+14, RR, RL, load_next_key, __movq);
533         round3(32+15, RL, RR, dummy2, dummy2);
534
535         final_permutation3(RR, RL);
536
537         ret;
538 ELF(.size _gcry_3des_amd64_crypt_blk3,.-_gcry_3des_amd64_crypt_blk3;)
539
540 .align 8
541 .globl  _gcry_3des_amd64_cbc_dec
542 ELF(.type   _gcry_3des_amd64_cbc_dec,@function;)
543 _gcry_3des_amd64_cbc_dec:
544         /* input:
545          *      %rdi: ctx, CTX
546          *      %rsi: dst (3 blocks)
547          *      %rdx: src (3 blocks)
548          *      %rcx: iv (64bit)
549          */
550
551         pushq %rbp;
552         pushq %rbx;
553         pushq %r12;
554         pushq %r13;
555         pushq %r14;
556         pushq %r15;
557
558         pushq %rsi; /*dst*/
559         pushq %rdx; /*src*/
560         pushq %rcx; /*iv*/
561
562         /* load input */
563         movl 0 * 4(%rdx), RL0d;
564         movl 1 * 4(%rdx), RR0d;
565         movl 2 * 4(%rdx), RL1d;
566         movl 3 * 4(%rdx), RR1d;
567         movl 4 * 4(%rdx), RL2d;
568         movl 5 * 4(%rdx), RR2d;
569
570         bswapl RL0d;
571         bswapl RR0d;
572         bswapl RL1d;
573         bswapl RR1d;
574         bswapl RL2d;
575         bswapl RR2d;
576
577         call _gcry_3des_amd64_crypt_blk3;
578
579         popq %rcx; /*iv*/
580         popq %rdx; /*src*/
581         popq %rsi; /*dst*/
582
583         bswapl RR0d;
584         bswapl RL0d;
585         bswapl RR1d;
586         bswapl RL1d;
587         bswapl RR2d;
588         bswapl RL2d;
589
590         movq 2 * 8(%rdx), RT0;
591         xorl 0 * 4(%rcx), RR0d;
592         xorl 1 * 4(%rcx), RL0d;
593         xorl 0 * 4(%rdx), RR1d;
594         xorl 1 * 4(%rdx), RL1d;
595         xorl 2 * 4(%rdx), RR2d;
596         xorl 3 * 4(%rdx), RL2d;
597         movq RT0, (%rcx); /* store new IV */
598
599         movl RR0d, 0 * 4(%rsi);
600         movl RL0d, 1 * 4(%rsi);
601         movl RR1d, 2 * 4(%rsi);
602         movl RL1d, 3 * 4(%rsi);
603         movl RR2d, 4 * 4(%rsi);
604         movl RL2d, 5 * 4(%rsi);
605
606         popq %r15;
607         popq %r14;
608         popq %r13;
609         popq %r12;
610         popq %rbx;
611         popq %rbp;
612
613         ret;
614 ELF(.size _gcry_3des_amd64_cbc_dec,.-_gcry_3des_amd64_cbc_dec;)
615
616 .align 8
617 .globl  _gcry_3des_amd64_ctr_enc
618 ELF(.type   _gcry_3des_amd64_ctr_enc,@function;)
619 _gcry_3des_amd64_ctr_enc:
620         /* input:
621          *      %rdi: ctx, CTX
622          *      %rsi: dst (3 blocks)
623          *      %rdx: src (3 blocks)
624          *      %rcx: iv (64bit)
625          */
626
627         pushq %rbp;
628         pushq %rbx;
629         pushq %r12;
630         pushq %r13;
631         pushq %r14;
632         pushq %r15;
633
634         pushq %rsi; /*dst*/
635         pushq %rdx; /*src*/
636         movq %rcx, RW2;
637
638         /* load IV and byteswap */
639         movq (RW2), RT0;
640         bswapq RT0;
641         movq RT0, RR0;
642
643         /* construct IVs */
644         leaq 1(RT0), RR1;
645         leaq 2(RT0), RR2;
646         leaq 3(RT0), RT0;
647         movq RR0, RL0;
648         movq RR1, RL1;
649         movq RR2, RL2;
650         bswapq RT0;
651         shrq $32, RL0;
652         shrq $32, RL1;
653         shrq $32, RL2;
654
655         /* store new IV */
656         movq RT0, (RW2);
657
658         call _gcry_3des_amd64_crypt_blk3;
659
660         popq %rdx; /*src*/
661         popq %rsi; /*dst*/
662
663         bswapl RR0d;
664         bswapl RL0d;
665         bswapl RR1d;
666         bswapl RL1d;
667         bswapl RR2d;
668         bswapl RL2d;
669
670         xorl 0 * 4(%rdx), RR0d;
671         xorl 1 * 4(%rdx), RL0d;
672         xorl 2 * 4(%rdx), RR1d;
673         xorl 3 * 4(%rdx), RL1d;
674         xorl 4 * 4(%rdx), RR2d;
675         xorl 5 * 4(%rdx), RL2d;
676
677         movl RR0d, 0 * 4(%rsi);
678         movl RL0d, 1 * 4(%rsi);
679         movl RR1d, 2 * 4(%rsi);
680         movl RL1d, 3 * 4(%rsi);
681         movl RR2d, 4 * 4(%rsi);
682         movl RL2d, 5 * 4(%rsi);
683
684         popq %r15;
685         popq %r14;
686         popq %r13;
687         popq %r12;
688         popq %rbx;
689         popq %rbp;
690
691         ret;
692 ELF(.size _gcry_3des_amd64_cbc_dec,.-_gcry_3des_amd64_cbc_dec;)
693
694 .align 8
695 .globl  _gcry_3des_amd64_cfb_dec
696 ELF(.type   _gcry_3des_amd64_cfb_dec,@function;)
697 _gcry_3des_amd64_cfb_dec:
698         /* input:
699          *      %rdi: ctx, CTX
700          *      %rsi: dst (3 blocks)
701          *      %rdx: src (3 blocks)
702          *      %rcx: iv (64bit)
703          */
704         pushq %rbp;
705         pushq %rbx;
706         pushq %r12;
707         pushq %r13;
708         pushq %r14;
709         pushq %r15;
710
711         pushq %rsi; /*dst*/
712         pushq %rdx; /*src*/
713         movq %rcx, RW2;
714
715         /* Load input */
716         movl 0 * 4(RW2), RL0d;
717         movl 1 * 4(RW2), RR0d;
718         movl 0 * 4(%rdx), RL1d;
719         movl 1 * 4(%rdx), RR1d;
720         movl 2 * 4(%rdx), RL2d;
721         movl 3 * 4(%rdx), RR2d;
722
723         bswapl RL0d;
724         bswapl RR0d;
725         bswapl RL1d;
726         bswapl RR1d;
727         bswapl RL2d;
728         bswapl RR2d;
729
730         /* Update IV */
731         movq 4 * 4(%rdx), RW0;
732         movq RW0, (RW2);
733
734         call _gcry_3des_amd64_crypt_blk3;
735
736         popq %rdx; /*src*/
737         popq %rsi; /*dst*/
738
739         bswapl RR0d;
740         bswapl RL0d;
741         bswapl RR1d;
742         bswapl RL1d;
743         bswapl RR2d;
744         bswapl RL2d;
745
746         xorl 0 * 4(%rdx), RR0d;
747         xorl 1 * 4(%rdx), RL0d;
748         xorl 2 * 4(%rdx), RR1d;
749         xorl 3 * 4(%rdx), RL1d;
750         xorl 4 * 4(%rdx), RR2d;
751         xorl 5 * 4(%rdx), RL2d;
752
753         movl RR0d, 0 * 4(%rsi);
754         movl RL0d, 1 * 4(%rsi);
755         movl RR1d, 2 * 4(%rsi);
756         movl RL1d, 3 * 4(%rsi);
757         movl RR2d, 4 * 4(%rsi);
758         movl RL2d, 5 * 4(%rsi);
759
760         popq %r15;
761         popq %r14;
762         popq %r13;
763         popq %r12;
764         popq %rbx;
765         popq %rbp;
766         ret;
767 ELF(.size _gcry_3des_amd64_cfb_dec,.-_gcry_3des_amd64_cfb_dec;)
768
769 .data
770 .align 16
771 .L_s1:
772         .quad 0x0010100001010400, 0x0000000000000000
773         .quad 0x0000100000010000, 0x0010100001010404
774         .quad 0x0010100001010004, 0x0000100000010404
775         .quad 0x0000000000000004, 0x0000100000010000
776         .quad 0x0000000000000400, 0x0010100001010400
777         .quad 0x0010100001010404, 0x0000000000000400
778         .quad 0x0010000001000404, 0x0010100001010004
779         .quad 0x0010000001000000, 0x0000000000000004
780         .quad 0x0000000000000404, 0x0010000001000400
781         .quad 0x0010000001000400, 0x0000100000010400
782         .quad 0x0000100000010400, 0x0010100001010000
783         .quad 0x0010100001010000, 0x0010000001000404
784         .quad 0x0000100000010004, 0x0010000001000004
785         .quad 0x0010000001000004, 0x0000100000010004
786         .quad 0x0000000000000000, 0x0000000000000404
787         .quad 0x0000100000010404, 0x0010000001000000
788         .quad 0x0000100000010000, 0x0010100001010404
789         .quad 0x0000000000000004, 0x0010100001010000
790         .quad 0x0010100001010400, 0x0010000001000000
791         .quad 0x0010000001000000, 0x0000000000000400
792         .quad 0x0010100001010004, 0x0000100000010000
793         .quad 0x0000100000010400, 0x0010000001000004
794         .quad 0x0000000000000400, 0x0000000000000004
795         .quad 0x0010000001000404, 0x0000100000010404
796         .quad 0x0010100001010404, 0x0000100000010004
797         .quad 0x0010100001010000, 0x0010000001000404
798         .quad 0x0010000001000004, 0x0000000000000404
799         .quad 0x0000100000010404, 0x0010100001010400
800         .quad 0x0000000000000404, 0x0010000001000400
801         .quad 0x0010000001000400, 0x0000000000000000
802         .quad 0x0000100000010004, 0x0000100000010400
803         .quad 0x0000000000000000, 0x0010100001010004
804 .L_s2:
805         .quad 0x0801080200100020, 0x0800080000000000
806         .quad 0x0000080000000000, 0x0001080200100020
807         .quad 0x0001000000100000, 0x0000000200000020
808         .quad 0x0801000200100020, 0x0800080200000020
809         .quad 0x0800000200000020, 0x0801080200100020
810         .quad 0x0801080000100000, 0x0800000000000000
811         .quad 0x0800080000000000, 0x0001000000100000
812         .quad 0x0000000200000020, 0x0801000200100020
813         .quad 0x0001080000100000, 0x0001000200100020
814         .quad 0x0800080200000020, 0x0000000000000000
815         .quad 0x0800000000000000, 0x0000080000000000
816         .quad 0x0001080200100020, 0x0801000000100000
817         .quad 0x0001000200100020, 0x0800000200000020
818         .quad 0x0000000000000000, 0x0001080000100000
819         .quad 0x0000080200000020, 0x0801080000100000
820         .quad 0x0801000000100000, 0x0000080200000020
821         .quad 0x0000000000000000, 0x0001080200100020
822         .quad 0x0801000200100020, 0x0001000000100000
823         .quad 0x0800080200000020, 0x0801000000100000
824         .quad 0x0801080000100000, 0x0000080000000000
825         .quad 0x0801000000100000, 0x0800080000000000
826         .quad 0x0000000200000020, 0x0801080200100020
827         .quad 0x0001080200100020, 0x0000000200000020
828         .quad 0x0000080000000000, 0x0800000000000000
829         .quad 0x0000080200000020, 0x0801080000100000
830         .quad 0x0001000000100000, 0x0800000200000020
831         .quad 0x0001000200100020, 0x0800080200000020
832         .quad 0x0800000200000020, 0x0001000200100020
833         .quad 0x0001080000100000, 0x0000000000000000
834         .quad 0x0800080000000000, 0x0000080200000020
835         .quad 0x0800000000000000, 0x0801000200100020
836         .quad 0x0801080200100020, 0x0001080000100000
837 .L_s3:
838         .quad 0x0000002000000208, 0x0000202008020200
839         .quad 0x0000000000000000, 0x0000200008020008
840         .quad 0x0000002008000200, 0x0000000000000000
841         .quad 0x0000202000020208, 0x0000002008000200
842         .quad 0x0000200000020008, 0x0000000008000008
843         .quad 0x0000000008000008, 0x0000200000020000
844         .quad 0x0000202008020208, 0x0000200000020008
845         .quad 0x0000200008020000, 0x0000002000000208
846         .quad 0x0000000008000000, 0x0000000000000008
847         .quad 0x0000202008020200, 0x0000002000000200
848         .quad 0x0000202000020200, 0x0000200008020000
849         .quad 0x0000200008020008, 0x0000202000020208
850         .quad 0x0000002008000208, 0x0000202000020200
851         .quad 0x0000200000020000, 0x0000002008000208
852         .quad 0x0000000000000008, 0x0000202008020208
853         .quad 0x0000002000000200, 0x0000000008000000
854         .quad 0x0000202008020200, 0x0000000008000000
855         .quad 0x0000200000020008, 0x0000002000000208
856         .quad 0x0000200000020000, 0x0000202008020200
857         .quad 0x0000002008000200, 0x0000000000000000
858         .quad 0x0000002000000200, 0x0000200000020008
859         .quad 0x0000202008020208, 0x0000002008000200
860         .quad 0x0000000008000008, 0x0000002000000200
861         .quad 0x0000000000000000, 0x0000200008020008
862         .quad 0x0000002008000208, 0x0000200000020000
863         .quad 0x0000000008000000, 0x0000202008020208
864         .quad 0x0000000000000008, 0x0000202000020208
865         .quad 0x0000202000020200, 0x0000000008000008
866         .quad 0x0000200008020000, 0x0000002008000208
867         .quad 0x0000002000000208, 0x0000200008020000
868         .quad 0x0000202000020208, 0x0000000000000008
869         .quad 0x0000200008020008, 0x0000202000020200
870 .L_s4:
871         .quad 0x1008020000002001, 0x1000020800002001
872         .quad 0x1000020800002001, 0x0000000800000000
873         .quad 0x0008020800002000, 0x1008000800000001
874         .quad 0x1008000000000001, 0x1000020000002001
875         .quad 0x0000000000000000, 0x0008020000002000
876         .quad 0x0008020000002000, 0x1008020800002001
877         .quad 0x1000000800000001, 0x0000000000000000
878         .quad 0x0008000800000000, 0x1008000000000001
879         .quad 0x1000000000000001, 0x0000020000002000
880         .quad 0x0008000000000000, 0x1008020000002001
881         .quad 0x0000000800000000, 0x0008000000000000
882         .quad 0x1000020000002001, 0x0000020800002000
883         .quad 0x1008000800000001, 0x1000000000000001
884         .quad 0x0000020800002000, 0x0008000800000000
885         .quad 0x0000020000002000, 0x0008020800002000
886         .quad 0x1008020800002001, 0x1000000800000001
887         .quad 0x0008000800000000, 0x1008000000000001
888         .quad 0x0008020000002000, 0x1008020800002001
889         .quad 0x1000000800000001, 0x0000000000000000
890         .quad 0x0000000000000000, 0x0008020000002000
891         .quad 0x0000020800002000, 0x0008000800000000
892         .quad 0x1008000800000001, 0x1000000000000001
893         .quad 0x1008020000002001, 0x1000020800002001
894         .quad 0x1000020800002001, 0x0000000800000000
895         .quad 0x1008020800002001, 0x1000000800000001
896         .quad 0x1000000000000001, 0x0000020000002000
897         .quad 0x1008000000000001, 0x1000020000002001
898         .quad 0x0008020800002000, 0x1008000800000001
899         .quad 0x1000020000002001, 0x0000020800002000
900         .quad 0x0008000000000000, 0x1008020000002001
901         .quad 0x0000000800000000, 0x0008000000000000
902         .quad 0x0000020000002000, 0x0008020800002000
903 .L_s5:
904         .quad 0x0000001000000100, 0x0020001002080100
905         .quad 0x0020000002080000, 0x0420001002000100
906         .quad 0x0000000000080000, 0x0000001000000100
907         .quad 0x0400000000000000, 0x0020000002080000
908         .quad 0x0400001000080100, 0x0000000000080000
909         .quad 0x0020001002000100, 0x0400001000080100
910         .quad 0x0420001002000100, 0x0420000002080000
911         .quad 0x0000001000080100, 0x0400000000000000
912         .quad 0x0020000002000000, 0x0400000000080000
913         .quad 0x0400000000080000, 0x0000000000000000
914         .quad 0x0400001000000100, 0x0420001002080100
915         .quad 0x0420001002080100, 0x0020001002000100
916         .quad 0x0420000002080000, 0x0400001000000100
917         .quad 0x0000000000000000, 0x0420000002000000
918         .quad 0x0020001002080100, 0x0020000002000000
919         .quad 0x0420000002000000, 0x0000001000080100
920         .quad 0x0000000000080000, 0x0420001002000100
921         .quad 0x0000001000000100, 0x0020000002000000
922         .quad 0x0400000000000000, 0x0020000002080000
923         .quad 0x0420001002000100, 0x0400001000080100
924         .quad 0x0020001002000100, 0x0400000000000000
925         .quad 0x0420000002080000, 0x0020001002080100
926         .quad 0x0400001000080100, 0x0000001000000100
927         .quad 0x0020000002000000, 0x0420000002080000
928         .quad 0x0420001002080100, 0x0000001000080100
929         .quad 0x0420000002000000, 0x0420001002080100
930         .quad 0x0020000002080000, 0x0000000000000000
931         .quad 0x0400000000080000, 0x0420000002000000
932         .quad 0x0000001000080100, 0x0020001002000100
933         .quad 0x0400001000000100, 0x0000000000080000
934         .quad 0x0000000000000000, 0x0400000000080000
935         .quad 0x0020001002080100, 0x0400001000000100
936 .L_s6:
937         .quad 0x0200000120000010, 0x0204000020000000
938         .quad 0x0000040000000000, 0x0204040120000010
939         .quad 0x0204000020000000, 0x0000000100000010
940         .quad 0x0204040120000010, 0x0004000000000000
941         .quad 0x0200040020000000, 0x0004040100000010
942         .quad 0x0004000000000000, 0x0200000120000010
943         .quad 0x0004000100000010, 0x0200040020000000
944         .quad 0x0200000020000000, 0x0000040100000010
945         .quad 0x0000000000000000, 0x0004000100000010
946         .quad 0x0200040120000010, 0x0000040000000000
947         .quad 0x0004040000000000, 0x0200040120000010
948         .quad 0x0000000100000010, 0x0204000120000010
949         .quad 0x0204000120000010, 0x0000000000000000
950         .quad 0x0004040100000010, 0x0204040020000000
951         .quad 0x0000040100000010, 0x0004040000000000
952         .quad 0x0204040020000000, 0x0200000020000000
953         .quad 0x0200040020000000, 0x0000000100000010
954         .quad 0x0204000120000010, 0x0004040000000000
955         .quad 0x0204040120000010, 0x0004000000000000
956         .quad 0x0000040100000010, 0x0200000120000010
957         .quad 0x0004000000000000, 0x0200040020000000
958         .quad 0x0200000020000000, 0x0000040100000010
959         .quad 0x0200000120000010, 0x0204040120000010
960         .quad 0x0004040000000000, 0x0204000020000000
961         .quad 0x0004040100000010, 0x0204040020000000
962         .quad 0x0000000000000000, 0x0204000120000010
963         .quad 0x0000000100000010, 0x0000040000000000
964         .quad 0x0204000020000000, 0x0004040100000010
965         .quad 0x0000040000000000, 0x0004000100000010
966         .quad 0x0200040120000010, 0x0000000000000000
967         .quad 0x0204040020000000, 0x0200000020000000
968         .quad 0x0004000100000010, 0x0200040120000010
969 .L_s7:
970         .quad 0x0002000000200000, 0x2002000004200002
971         .quad 0x2000000004000802, 0x0000000000000000
972         .quad 0x0000000000000800, 0x2000000004000802
973         .quad 0x2002000000200802, 0x0002000004200800
974         .quad 0x2002000004200802, 0x0002000000200000
975         .quad 0x0000000000000000, 0x2000000004000002
976         .quad 0x2000000000000002, 0x0000000004000000
977         .quad 0x2002000004200002, 0x2000000000000802
978         .quad 0x0000000004000800, 0x2002000000200802
979         .quad 0x2002000000200002, 0x0000000004000800
980         .quad 0x2000000004000002, 0x0002000004200000
981         .quad 0x0002000004200800, 0x2002000000200002
982         .quad 0x0002000004200000, 0x0000000000000800
983         .quad 0x2000000000000802, 0x2002000004200802
984         .quad 0x0002000000200800, 0x2000000000000002
985         .quad 0x0000000004000000, 0x0002000000200800
986         .quad 0x0000000004000000, 0x0002000000200800
987         .quad 0x0002000000200000, 0x2000000004000802
988         .quad 0x2000000004000802, 0x2002000004200002
989         .quad 0x2002000004200002, 0x2000000000000002
990         .quad 0x2002000000200002, 0x0000000004000000
991         .quad 0x0000000004000800, 0x0002000000200000
992         .quad 0x0002000004200800, 0x2000000000000802
993         .quad 0x2002000000200802, 0x0002000004200800
994         .quad 0x2000000000000802, 0x2000000004000002
995         .quad 0x2002000004200802, 0x0002000004200000
996         .quad 0x0002000000200800, 0x0000000000000000
997         .quad 0x2000000000000002, 0x2002000004200802
998         .quad 0x0000000000000000, 0x2002000000200802
999         .quad 0x0002000004200000, 0x0000000000000800
1000         .quad 0x2000000004000002, 0x0000000004000800
1001         .quad 0x0000000000000800, 0x2002000000200002
1002 .L_s8:
1003         .quad 0x0100010410001000, 0x0000010000001000
1004         .quad 0x0000000000040000, 0x0100010410041000
1005         .quad 0x0100000010000000, 0x0100010410001000
1006         .quad 0x0000000400000000, 0x0100000010000000
1007         .quad 0x0000000400040000, 0x0100000010040000
1008         .quad 0x0100010410041000, 0x0000010000041000
1009         .quad 0x0100010010041000, 0x0000010400041000
1010         .quad 0x0000010000001000, 0x0000000400000000
1011         .quad 0x0100000010040000, 0x0100000410000000
1012         .quad 0x0100010010001000, 0x0000010400001000
1013         .quad 0x0000010000041000, 0x0000000400040000
1014         .quad 0x0100000410040000, 0x0100010010041000
1015         .quad 0x0000010400001000, 0x0000000000000000
1016         .quad 0x0000000000000000, 0x0100000410040000
1017         .quad 0x0100000410000000, 0x0100010010001000
1018         .quad 0x0000010400041000, 0x0000000000040000
1019         .quad 0x0000010400041000, 0x0000000000040000
1020         .quad 0x0100010010041000, 0x0000010000001000
1021         .quad 0x0000000400000000, 0x0100000410040000
1022         .quad 0x0000010000001000, 0x0000010400041000
1023         .quad 0x0100010010001000, 0x0000000400000000
1024         .quad 0x0100000410000000, 0x0100000010040000
1025         .quad 0x0100000410040000, 0x0100000010000000
1026         .quad 0x0000000000040000, 0x0100010410001000
1027         .quad 0x0000000000000000, 0x0100010410041000
1028         .quad 0x0000000400040000, 0x0100000410000000
1029         .quad 0x0100000010040000, 0x0100010010001000
1030         .quad 0x0100010410001000, 0x0000000000000000
1031         .quad 0x0100010410041000, 0x0000010000041000
1032         .quad 0x0000010000041000, 0x0000010400001000
1033         .quad 0x0000010400001000, 0x0000000400040000
1034         .quad 0x0100000010000000, 0x0100010010041000
1035
1036 #endif
1037 #endif