doc: Fix typo.
[libgcrypt.git] / cipher / twofish-amd64.S
1 /* twofish-amd64.S  -  AMD64 assembly implementation of Twofish 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_TWOFISH)
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 .text
39
40 /* structure of TWOFISH_context: */
41 #define s0 0
42 #define s1 ((s0) + 4 * 256)
43 #define s2 ((s1) + 4 * 256)
44 #define s3 ((s2) + 4 * 256)
45 #define w  ((s3) + 4 * 256)
46 #define k  ((w) + 4 * 8)
47
48 /* register macros */
49 #define CTX     %rdi
50
51 #define RA      %rax
52 #define RB      %rbx
53 #define RC      %rcx
54 #define RD      %rdx
55
56 #define RAd     %eax
57 #define RBd     %ebx
58 #define RCd     %ecx
59 #define RDd     %edx
60
61 #define RAbl    %al
62 #define RBbl    %bl
63 #define RCbl    %cl
64 #define RDbl    %dl
65
66 #define RAbh    %ah
67 #define RBbh    %bh
68 #define RCbh    %ch
69 #define RDbh    %dh
70
71 #define RX      %r8
72 #define RY      %r9
73
74 #define RXd     %r8d
75 #define RYd     %r9d
76
77 #define RT0     %rsi
78 #define RT1     %rbp
79 #define RT2     %r10
80 #define RT3     %r11
81
82 #define RT0d    %esi
83 #define RT1d    %ebp
84 #define RT2d    %r10d
85 #define RT3d    %r11d
86
87 /***********************************************************************
88  * AMD64 assembly implementation of the Twofish cipher
89  ***********************************************************************/
90 #define enc_g1_2(a, b, x, y) \
91         movzbl b ## bl, RT3d; \
92         movzbl b ## bh, RT1d; \
93         movzbl a ## bl, RT2d; \
94         movzbl a ## bh, RT0d; \
95         rorl $16, b ## d; \
96         rorl $16, a ## d; \
97         movl s1(CTX, RT3, 4), RYd; \
98         movzbl b ## bl, RT3d; \
99         movl s0(CTX, RT2, 4), RXd; \
100         movzbl a ## bl, RT2d; \
101         xorl s2(CTX, RT1, 4), RYd; \
102         movzbl b ## bh, RT1d; \
103         xorl s1(CTX, RT0, 4), RXd; \
104         movzbl a ## bh, RT0d; \
105         rorl $16, b ## d; \
106         rorl $16, a ## d; \
107         xorl s3(CTX, RT3, 4), RYd; \
108         xorl s2(CTX, RT2, 4), RXd; \
109         xorl s0(CTX, RT1, 4), RYd; \
110         xorl s3(CTX, RT0, 4), RXd;
111
112 #define dec_g1_2(a, b, x, y) \
113         movzbl a ## bl, RT2d; \
114         movzbl a ## bh, RT0d; \
115         movzbl b ## bl, RT3d; \
116         movzbl b ## bh, RT1d; \
117         rorl $16, a ## d; \
118         rorl $16, b ## d; \
119         movl s0(CTX, RT2, 4), RXd; \
120         movzbl a ## bl, RT2d; \
121         movl s1(CTX, RT3, 4), RYd; \
122         movzbl b ## bl, RT3d; \
123         xorl s1(CTX, RT0, 4), RXd; \
124         movzbl a ## bh, RT0d; \
125         xorl s2(CTX, RT1, 4), RYd; \
126         movzbl b ## bh, RT1d; \
127         rorl $16, a ## d; \
128         rorl $16, b ## d; \
129         xorl s2(CTX, RT2, 4), RXd; \
130         xorl s3(CTX, RT3, 4), RYd; \
131         xorl s3(CTX, RT0, 4), RXd; \
132         xorl s0(CTX, RT1, 4), RYd;
133
134 #define encrypt_round(ra, rb, rc, rd, n) \
135         enc_g1_2(##ra, ##rb, RX, RY); \
136         \
137         leal (RXd, RYd, 2), RT0d; \
138         addl RYd, RXd; \
139         addl (k + 8 * (n) + 4)(CTX), RT0d; \
140         roll $1, rd ## d; \
141         addl (k + 8 * (n))(CTX), RXd; \
142         xorl RT0d, rd ## d; \
143         xorl RXd, rc ## d; \
144         rorl $1, rc ## d;
145
146 #define decrypt_round(ra, rb, rc, rd, n) \
147         dec_g1_2(##ra, ##rb, RX, RY); \
148         \
149         leal (RXd, RYd, 2), RT0d; \
150         addl RYd, RXd; \
151         addl (k + 8 * (n) + 4)(CTX), RT0d; \
152         roll $1, rc ## d; \
153         addl (k + 8 * (n))(CTX), RXd; \
154         xorl RXd, rc ## d; \
155         xorl RT0d, rd ## d; \
156         rorl $1, rd ## d;
157
158 #define encrypt_cycle(a, b, c, d, nc) \
159         encrypt_round(##a, ##b, ##c, ##d, (nc) * 2); \
160         encrypt_round(##c, ##d, ##a, ##b, (nc) * 2 + 1);
161
162 #define decrypt_cycle(a, b, c, d, nc) \
163         decrypt_round(##c, ##d, ##a, ##b, (nc) * 2 + 1); \
164         decrypt_round(##a, ##b, ##c, ##d, (nc) * 2);
165
166 #define inpack(in, n, x, m) \
167         movl (4 * (n))(in), x; \
168         xorl (w + 4 * (m))(CTX), x;
169
170 #define outunpack(out, n, x, m) \
171         xorl (w + 4 * (m))(CTX), x; \
172         movl x, (4 * (n))(out);
173
174 .align 8
175 .globl _gcry_twofish_amd64_encrypt_block
176 ELF(.type   _gcry_twofish_amd64_encrypt_block,@function;)
177
178 _gcry_twofish_amd64_encrypt_block:
179         /* input:
180          *      %rdi: context, CTX
181          *      %rsi: dst
182          *      %rdx: src
183          */
184         subq $(3 * 8), %rsp;
185         movq %rsi, (0 * 8)(%rsp);
186         movq %rbp, (1 * 8)(%rsp);
187         movq %rbx, (2 * 8)(%rsp);
188
189         movq %rdx, RX;
190         inpack(RX, 0, RAd, 0);
191         inpack(RX, 1, RBd, 1);
192         inpack(RX, 2, RCd, 2);
193         inpack(RX, 3, RDd, 3);
194
195         encrypt_cycle(RA, RB, RC, RD, 0);
196         encrypt_cycle(RA, RB, RC, RD, 1);
197         encrypt_cycle(RA, RB, RC, RD, 2);
198         encrypt_cycle(RA, RB, RC, RD, 3);
199         encrypt_cycle(RA, RB, RC, RD, 4);
200         encrypt_cycle(RA, RB, RC, RD, 5);
201         encrypt_cycle(RA, RB, RC, RD, 6);
202         encrypt_cycle(RA, RB, RC, RD, 7);
203
204         movq (0 * 8)(%rsp), RX; /*dst*/
205         outunpack(RX, 0, RCd, 4);
206         outunpack(RX, 1, RDd, 5);
207         outunpack(RX, 2, RAd, 6);
208         outunpack(RX, 3, RBd, 7);
209
210         movq (2 * 8)(%rsp), %rbx;
211         movq (1 * 8)(%rsp), %rbp;
212         addq $(3 * 8), %rsp;
213
214         ret;
215 ELF(.size _gcry_twofish_amd64_encrypt_block,.-_gcry_twofish_amd64_encrypt_block;)
216
217 .align 8
218 .globl _gcry_twofish_amd64_decrypt_block
219 ELF(.type   _gcry_twofish_amd64_decrypt_block,@function;)
220
221 _gcry_twofish_amd64_decrypt_block:
222         /* input:
223          *      %rdi: context, CTX
224          *      %rsi: dst
225          *      %rdx: src
226          */
227         subq $(3 * 8), %rsp;
228         movq %rsi, (0 * 8)(%rsp);
229         movq %rbp, (1 * 8)(%rsp);
230         movq %rbx, (2 * 8)(%rsp);
231
232         movq %rdx, RX;
233         inpack(RX, 0, RCd, 4);
234         inpack(RX, 1, RDd, 5);
235         inpack(RX, 2, RAd, 6);
236         inpack(RX, 3, RBd, 7);
237
238         decrypt_cycle(RA, RB, RC, RD, 7);
239         decrypt_cycle(RA, RB, RC, RD, 6);
240         decrypt_cycle(RA, RB, RC, RD, 5);
241         decrypt_cycle(RA, RB, RC, RD, 4);
242         decrypt_cycle(RA, RB, RC, RD, 3);
243         decrypt_cycle(RA, RB, RC, RD, 2);
244         decrypt_cycle(RA, RB, RC, RD, 1);
245         decrypt_cycle(RA, RB, RC, RD, 0);
246
247         movq (0 * 8)(%rsp), RX; /*dst*/
248         outunpack(RX, 0, RAd, 0);
249         outunpack(RX, 1, RBd, 1);
250         outunpack(RX, 2, RCd, 2);
251         outunpack(RX, 3, RDd, 3);
252
253         movq (2 * 8)(%rsp), %rbx;
254         movq (1 * 8)(%rsp), %rbp;
255         addq $(3 * 8), %rsp;
256
257         ret;
258 ELF(.size _gcry_twofish_amd64_encrypt_block,.-_gcry_twofish_amd64_encrypt_block;)
259
260 #undef CTX
261
262 #undef RA
263 #undef RB
264 #undef RC
265 #undef RD
266
267 #undef RAd
268 #undef RBd
269 #undef RCd
270 #undef RDd
271
272 #undef RAbl
273 #undef RBbl
274 #undef RCbl
275 #undef RDbl
276
277 #undef RAbh
278 #undef RBbh
279 #undef RCbh
280 #undef RDbh
281
282 #undef RX
283 #undef RY
284
285 #undef RXd
286 #undef RYd
287
288 #undef RT0
289 #undef RT1
290 #undef RT2
291 #undef RT3
292
293 #undef RT0d
294 #undef RT1d
295 #undef RT2d
296 #undef RT3d
297
298 /***********************************************************************
299  * AMD64 assembly implementation of the Twofish cipher, 3-way parallel
300  ***********************************************************************/
301 #define CTX %rdi
302 #define RIO %rdx
303
304 #define RAB0 %rax
305 #define RAB1 %rbx
306 #define RAB2 %rcx
307
308 #define RAB0d %eax
309 #define RAB1d %ebx
310 #define RAB2d %ecx
311
312 #define RAB0bh %ah
313 #define RAB1bh %bh
314 #define RAB2bh %ch
315
316 #define RAB0bl %al
317 #define RAB1bl %bl
318 #define RAB2bl %cl
319
320 #define RCD0 %r8
321 #define RCD1 %r9
322 #define RCD2 %r10
323
324 #define RCD0d %r8d
325 #define RCD1d %r9d
326 #define RCD2d %r10d
327
328 #define RX0 %rbp
329 #define RX1 %r11
330 #define RX2 %r12
331
332 #define RX0d %ebp
333 #define RX1d %r11d
334 #define RX2d %r12d
335
336 #define RY0 %r13
337 #define RY1 %r14
338 #define RY2 %r15
339
340 #define RY0d %r13d
341 #define RY1d %r14d
342 #define RY2d %r15d
343
344 #define RT0 %rdx
345 #define RT1 %rsi
346
347 #define RT0d %edx
348 #define RT1d %esi
349
350 #define do16bit_ror(rot, op1, op2, T0, T1, tmp1, tmp2, ab, dst) \
351         movzbl ab ## bl,                tmp2 ## d; \
352         movzbl ab ## bh,                tmp1 ## d; \
353         rorq $(rot),                    ab; \
354         op1##l T0(CTX, tmp2, 4),        dst ## d; \
355         op2##l T1(CTX, tmp1, 4),        dst ## d;
356
357 /*
358  * Combined G1 & G2 function. Reordered with help of rotates to have moves
359  * at beginning.
360  */
361 #define g1g2_3(ab, cd, Tx0, Tx1, Tx2, Tx3, Ty0, Ty1, Ty2, Ty3, x, y) \
362         /* G1,1 && G2,1 */ \
363         do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 0, ab ## 0, x ## 0); \
364         do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 0, ab ## 0, y ## 0); \
365         \
366         do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 1, ab ## 1, x ## 1); \
367         do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 1, ab ## 1, y ## 1); \
368         \
369         do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 2, ab ## 2, x ## 2); \
370         do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 2, ab ## 2, y ## 2); \
371         \
372         /* G1,2 && G2,2 */ \
373         do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 0, x ## 0); \
374         do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 0, y ## 0); \
375         xchgq cd ## 0, ab ## 0; \
376         \
377         do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 1, x ## 1); \
378         do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 1, y ## 1); \
379         xchgq cd ## 1, ab ## 1; \
380         \
381         do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 2, x ## 2); \
382         do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 2, y ## 2); \
383         xchgq cd ## 2, ab ## 2;
384
385 #define enc_round_end(ab, x, y, n) \
386         addl y ## d,                    x ## d; \
387         addl x ## d,                    y ## d; \
388         addl k+4*(2*(n))(CTX),          x ## d; \
389         xorl ab ## d,                   x ## d; \
390         addl k+4*(2*(n)+1)(CTX),        y ## d; \
391         shrq $32,                       ab; \
392         roll $1,                        ab ## d; \
393         xorl y ## d,                    ab ## d; \
394         shlq $32,                       ab; \
395         rorl $1,                        x ## d; \
396         orq x,                          ab;
397
398 #define dec_round_end(ba, x, y, n) \
399         addl y ## d,                    x ## d; \
400         addl x ## d,                    y ## d; \
401         addl k+4*(2*(n))(CTX),          x ## d; \
402         addl k+4*(2*(n)+1)(CTX),        y ## d; \
403         xorl ba ## d,                   y ## d; \
404         shrq $32,                       ba; \
405         roll $1,                        ba ## d; \
406         xorl x ## d,                    ba ## d; \
407         shlq $32,                       ba; \
408         rorl $1,                        y ## d; \
409         orq y,                          ba;
410
411 #define encrypt_round3(ab, cd, n) \
412         g1g2_3(ab, cd, s0, s1, s2, s3, s0, s1, s2, s3, RX, RY); \
413         \
414         enc_round_end(ab ## 0, RX0, RY0, n); \
415         enc_round_end(ab ## 1, RX1, RY1, n); \
416         enc_round_end(ab ## 2, RX2, RY2, n);
417
418 #define decrypt_round3(ba, dc, n) \
419         g1g2_3(ba, dc, s1, s2, s3, s0, s3, s0, s1, s2, RY, RX); \
420         \
421         dec_round_end(ba ## 0, RX0, RY0, n); \
422         dec_round_end(ba ## 1, RX1, RY1, n); \
423         dec_round_end(ba ## 2, RX2, RY2, n);
424
425 #define encrypt_cycle3(ab, cd, n) \
426         encrypt_round3(ab, cd, n*2); \
427         encrypt_round3(ab, cd, (n*2)+1);
428
429 #define decrypt_cycle3(ba, dc, n) \
430         decrypt_round3(ba, dc, (n*2)+1); \
431         decrypt_round3(ba, dc, (n*2));
432
433 #define inpack3(xy, m) \
434         xorq w+4*m(CTX),                xy ## 0; \
435         xorq w+4*m(CTX),                xy ## 1; \
436         xorq w+4*m(CTX),                xy ## 2;
437
438 #define outunpack3(xy, m) \
439         xorq w+4*m(CTX),                xy ## 0; \
440         xorq w+4*m(CTX),                xy ## 1; \
441         xorq w+4*m(CTX),                xy ## 2;
442
443 #define inpack_enc3() \
444         inpack3(RAB, 0); \
445         inpack3(RCD, 2);
446
447 #define outunpack_enc3() \
448         outunpack3(RAB, 6); \
449         outunpack3(RCD, 4);
450
451 #define inpack_dec3() \
452         inpack3(RAB, 4); \
453         rorq $32,                       RAB0; \
454         rorq $32,                       RAB1; \
455         rorq $32,                       RAB2; \
456         inpack3(RCD, 6); \
457         rorq $32,                       RCD0; \
458         rorq $32,                       RCD1; \
459         rorq $32,                       RCD2;
460
461 #define outunpack_dec3() \
462         rorq $32,                       RCD0; \
463         rorq $32,                       RCD1; \
464         rorq $32,                       RCD2; \
465         outunpack3(RCD, 0); \
466         rorq $32,                       RAB0; \
467         rorq $32,                       RAB1; \
468         rorq $32,                       RAB2; \
469         outunpack3(RAB, 2);
470
471 .align 8
472 ELF(.type __twofish_enc_blk3,@function;)
473
474 __twofish_enc_blk3:
475         /* input:
476          *      %rdi: ctx, CTX
477          *      RAB0,RCD0,RAB1,RCD1,RAB2,RCD2: three plaintext blocks
478          * output:
479          *      RCD0,RAB0,RCD1,RAB1,RCD2,RAB2: three ciphertext blocks
480          */
481         inpack_enc3();
482
483         encrypt_cycle3(RAB, RCD, 0);
484         encrypt_cycle3(RAB, RCD, 1);
485         encrypt_cycle3(RAB, RCD, 2);
486         encrypt_cycle3(RAB, RCD, 3);
487         encrypt_cycle3(RAB, RCD, 4);
488         encrypt_cycle3(RAB, RCD, 5);
489         encrypt_cycle3(RAB, RCD, 6);
490         encrypt_cycle3(RAB, RCD, 7);
491
492         outunpack_enc3();
493
494         ret;
495 ELF(.size __twofish_enc_blk3,.-__twofish_enc_blk3;)
496
497 .align 8
498 ELF(.type  __twofish_dec_blk3,@function;)
499
500 __twofish_dec_blk3:
501         /* input:
502          *      %rdi: ctx, CTX
503          *      RAB0,RCD0,RAB1,RCD1,RAB2,RCD2: three ciphertext blocks
504          * output:
505          *      RCD0,RAB0,RCD1,RAB1,RCD2,RAB2: three plaintext blocks
506          */
507         inpack_dec3();
508
509         decrypt_cycle3(RAB, RCD, 7);
510         decrypt_cycle3(RAB, RCD, 6);
511         decrypt_cycle3(RAB, RCD, 5);
512         decrypt_cycle3(RAB, RCD, 4);
513         decrypt_cycle3(RAB, RCD, 3);
514         decrypt_cycle3(RAB, RCD, 2);
515         decrypt_cycle3(RAB, RCD, 1);
516         decrypt_cycle3(RAB, RCD, 0);
517
518         outunpack_dec3();
519
520         ret;
521 ELF(.size __twofish_dec_blk3,.-__twofish_dec_blk3;)
522
523 .align 8
524 .globl _gcry_twofish_amd64_ctr_enc
525 ELF(.type   _gcry_twofish_amd64_ctr_enc,@function;)
526 _gcry_twofish_amd64_ctr_enc:
527         /* input:
528          *      %rdi: ctx, CTX
529          *      %rsi: dst (3 blocks)
530          *      %rdx: src (3 blocks)
531          *      %rcx: iv (big endian, 128bit)
532          */
533         subq $(8 * 8), %rsp;
534         movq %rbp, (0 * 8)(%rsp);
535         movq %rbx, (1 * 8)(%rsp);
536         movq %r12, (2 * 8)(%rsp);
537         movq %r13, (3 * 8)(%rsp);
538         movq %r14, (4 * 8)(%rsp);
539         movq %r15, (5 * 8)(%rsp);
540
541         movq %rsi, (6 * 8)(%rsp);
542         movq %rdx, (7 * 8)(%rsp);
543         movq %rcx, RX0;
544
545         /* load IV and byteswap */
546         movq 8(RX0), RT0;
547         movq 0(RX0), RT1;
548         movq RT0, RCD0;
549         movq RT1, RAB0;
550         bswapq RT0;
551         bswapq RT1;
552
553         /* construct IVs */
554         movq RT0, RCD1;
555         movq RT1, RAB1;
556         movq RT0, RCD2;
557         movq RT1, RAB2;
558         addq $1, RCD1;
559         adcq $0, RAB1;
560         bswapq RCD1;
561         bswapq RAB1;
562         addq $2, RCD2;
563         adcq $0, RAB2;
564         bswapq RCD2;
565         bswapq RAB2;
566         addq $3, RT0;
567         adcq $0, RT1;
568         bswapq RT0;
569         bswapq RT1;
570
571         /* store new IV */
572         movq RT0, 8(RX0);
573         movq RT1, 0(RX0);
574
575         call __twofish_enc_blk3;
576
577         movq (7 * 8)(%rsp), RX0; /*src*/
578         movq (6 * 8)(%rsp), RX1; /*dst*/
579
580         /* XOR key-stream with plaintext */
581         xorq (0 * 8)(RX0), RCD0;
582         xorq (1 * 8)(RX0), RAB0;
583         xorq (2 * 8)(RX0), RCD1;
584         xorq (3 * 8)(RX0), RAB1;
585         xorq (4 * 8)(RX0), RCD2;
586         xorq (5 * 8)(RX0), RAB2;
587         movq RCD0, (0 * 8)(RX1);
588         movq RAB0, (1 * 8)(RX1);
589         movq RCD1, (2 * 8)(RX1);
590         movq RAB1, (3 * 8)(RX1);
591         movq RCD2, (4 * 8)(RX1);
592         movq RAB2, (5 * 8)(RX1);
593
594         movq (0 * 8)(%rsp), %rbp;
595         movq (1 * 8)(%rsp), %rbx;
596         movq (2 * 8)(%rsp), %r12;
597         movq (3 * 8)(%rsp), %r13;
598         movq (4 * 8)(%rsp), %r14;
599         movq (5 * 8)(%rsp), %r15;
600         addq $(8 * 8), %rsp;
601
602         ret;
603 ELF(.size _gcry_twofish_amd64_ctr_enc,.-_gcry_twofish_amd64_ctr_enc;)
604
605 .align 8
606 .globl _gcry_twofish_amd64_cbc_dec
607 ELF(.type   _gcry_twofish_amd64_cbc_dec,@function;)
608 _gcry_twofish_amd64_cbc_dec:
609         /* input:
610          *      %rdi: ctx, CTX
611          *      %rsi: dst (3 blocks)
612          *      %rdx: src (3 blocks)
613          *      %rcx: iv (128bit)
614          */
615         subq $(9 * 8), %rsp;
616         movq %rbp, (0 * 8)(%rsp);
617         movq %rbx, (1 * 8)(%rsp);
618         movq %r12, (2 * 8)(%rsp);
619         movq %r13, (3 * 8)(%rsp);
620         movq %r14, (4 * 8)(%rsp);
621         movq %r15, (5 * 8)(%rsp);
622
623         movq %rsi, (6 * 8)(%rsp);
624         movq %rdx, (7 * 8)(%rsp);
625         movq %rcx, (8 * 8)(%rsp);
626         movq %rdx, RX0;
627
628         /* load input */
629         movq (0 * 8)(RX0), RAB0;
630         movq (1 * 8)(RX0), RCD0;
631         movq (2 * 8)(RX0), RAB1;
632         movq (3 * 8)(RX0), RCD1;
633         movq (4 * 8)(RX0), RAB2;
634         movq (5 * 8)(RX0), RCD2;
635
636         call __twofish_dec_blk3;
637
638         movq (8 * 8)(%rsp), RT0; /*iv*/
639         movq (7 * 8)(%rsp), RX0; /*src*/
640         movq (6 * 8)(%rsp), RX1; /*dst*/
641
642         movq (4 * 8)(RX0), RY0;
643         movq (5 * 8)(RX0), RY1;
644         xorq (0 * 8)(RT0), RCD0;
645         xorq (1 * 8)(RT0), RAB0;
646         xorq (0 * 8)(RX0), RCD1;
647         xorq (1 * 8)(RX0), RAB1;
648         xorq (2 * 8)(RX0), RCD2;
649         xorq (3 * 8)(RX0), RAB2;
650         movq RY0, (0 * 8)(RT0);
651         movq RY1, (1 * 8)(RT0);
652
653         movq RCD0, (0 * 8)(RX1);
654         movq RAB0, (1 * 8)(RX1);
655         movq RCD1, (2 * 8)(RX1);
656         movq RAB1, (3 * 8)(RX1);
657         movq RCD2, (4 * 8)(RX1);
658         movq RAB2, (5 * 8)(RX1);
659
660         movq (0 * 8)(%rsp), %rbp;
661         movq (1 * 8)(%rsp), %rbx;
662         movq (2 * 8)(%rsp), %r12;
663         movq (3 * 8)(%rsp), %r13;
664         movq (4 * 8)(%rsp), %r14;
665         movq (5 * 8)(%rsp), %r15;
666         addq $(9 * 8), %rsp;
667
668         ret;
669 ELF(.size _gcry_twofish_amd64_cbc_dec,.-_gcry_twofish_amd64_cbc_dec;)
670
671 .align 8
672 .globl _gcry_twofish_amd64_cfb_dec
673 ELF(.type   _gcry_twofish_amd64_cfb_dec,@function;)
674 _gcry_twofish_amd64_cfb_dec:
675         /* input:
676          *      %rdi: ctx, CTX
677          *      %rsi: dst (3 blocks)
678          *      %rdx: src (3 blocks)
679          *      %rcx: iv (128bit)
680          */
681         subq $(8 * 8), %rsp;
682         movq %rbp, (0 * 8)(%rsp);
683         movq %rbx, (1 * 8)(%rsp);
684         movq %r12, (2 * 8)(%rsp);
685         movq %r13, (3 * 8)(%rsp);
686         movq %r14, (4 * 8)(%rsp);
687         movq %r15, (5 * 8)(%rsp);
688
689         movq %rsi, (6 * 8)(%rsp);
690         movq %rdx, (7 * 8)(%rsp);
691         movq %rdx, RX0;
692         movq %rcx, RX1;
693
694         /* load input */
695         movq (0 * 8)(RX1), RAB0;
696         movq (1 * 8)(RX1), RCD0;
697         movq (0 * 8)(RX0), RAB1;
698         movq (1 * 8)(RX0), RCD1;
699         movq (2 * 8)(RX0), RAB2;
700         movq (3 * 8)(RX0), RCD2;
701
702         /* Update IV */
703         movq (4 * 8)(RX0), RY0;
704         movq (5 * 8)(RX0), RY1;
705         movq RY0, (0 * 8)(RX1);
706         movq RY1, (1 * 8)(RX1);
707
708         call __twofish_enc_blk3;
709
710         movq (7 * 8)(%rsp), RX0; /*src*/
711         movq (6 * 8)(%rsp), RX1; /*dst*/
712
713         xorq (0 * 8)(RX0), RCD0;
714         xorq (1 * 8)(RX0), RAB0;
715         xorq (2 * 8)(RX0), RCD1;
716         xorq (3 * 8)(RX0), RAB1;
717         xorq (4 * 8)(RX0), RCD2;
718         xorq (5 * 8)(RX0), RAB2;
719         movq RCD0, (0 * 8)(RX1);
720         movq RAB0, (1 * 8)(RX1);
721         movq RCD1, (2 * 8)(RX1);
722         movq RAB1, (3 * 8)(RX1);
723         movq RCD2, (4 * 8)(RX1);
724         movq RAB2, (5 * 8)(RX1);
725
726         movq (0 * 8)(%rsp), %rbp;
727         movq (1 * 8)(%rsp), %rbx;
728         movq (2 * 8)(%rsp), %r12;
729         movq (3 * 8)(%rsp), %r13;
730         movq (4 * 8)(%rsp), %r14;
731         movq (5 * 8)(%rsp), %r15;
732         addq $(8 * 8), %rsp;
733
734         ret;
735 ELF(.size _gcry_twofish_amd64_cfb_dec,.-_gcry_twofish_amd64_cfb_dec;)
736
737 .align 8
738 .globl _gcry_twofish_amd64_ocb_enc
739 ELF(.type   _gcry_twofish_amd64_ocb_enc,@function;)
740 _gcry_twofish_amd64_ocb_enc:
741         /* input:
742          *      %rdi: ctx, CTX
743          *      %rsi: dst (3 blocks)
744          *      %rdx: src (3 blocks)
745          *      %rcx: offset
746          *      %r8 : checksum
747          *      %r9 : L pointers (void *L[3])
748          */
749         subq $(8 * 8), %rsp;
750         movq %rbp, (0 * 8)(%rsp);
751         movq %rbx, (1 * 8)(%rsp);
752         movq %r12, (2 * 8)(%rsp);
753         movq %r13, (3 * 8)(%rsp);
754         movq %r14, (4 * 8)(%rsp);
755         movq %r15, (5 * 8)(%rsp);
756
757         movq %rsi, (6 * 8)(%rsp);
758         movq %rdx, RX0;
759         movq %rcx, RX1;
760         movq %r8, RX2;
761         movq %r9, RY0;
762         movq %rsi, RY1;
763
764         /* Load offset */
765         movq (0 * 8)(RX1), RT0;
766         movq (1 * 8)(RX1), RT1;
767
768         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
769         movq (RY0), RY2;
770         xorq (0 * 8)(RY2), RT0;
771         xorq (1 * 8)(RY2), RT1;
772         movq (0 * 8)(RX0), RAB0;
773         movq (1 * 8)(RX0), RCD0;
774         /* Store Offset_i */
775         movq RT0, (0 * 8)(RY1);
776         movq RT1, (1 * 8)(RY1);
777         /* Checksum_i = Checksum_{i-1} xor P_i  */
778         xor RAB0, (0 * 8)(RX2);
779         xor RCD0, (1 * 8)(RX2);
780         /* PX_i = P_i xor Offset_i */
781         xorq RT0, RAB0;
782         xorq RT1, RCD0;
783
784         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
785         movq 8(RY0), RY2;
786         xorq (0 * 8)(RY2), RT0;
787         xorq (1 * 8)(RY2), RT1;
788         movq (2 * 8)(RX0), RAB1;
789         movq (3 * 8)(RX0), RCD1;
790         /* Store Offset_i */
791         movq RT0, (2 * 8)(RY1);
792         movq RT1, (3 * 8)(RY1);
793         /* Checksum_i = Checksum_{i-1} xor P_i  */
794         xor RAB1, (0 * 8)(RX2);
795         xor RCD1, (1 * 8)(RX2);
796         /* PX_i = P_i xor Offset_i */
797         xorq RT0, RAB1;
798         xorq RT1, RCD1;
799
800         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
801         movq 16(RY0), RY2;
802         xorq (0 * 8)(RY2), RT0;
803         xorq (1 * 8)(RY2), RT1;
804         movq (4 * 8)(RX0), RAB2;
805         movq (5 * 8)(RX0), RCD2;
806         /* Store Offset_i */
807         movq RT0, (4 * 8)(RY1);
808         movq RT1, (5 * 8)(RY1);
809         /* Checksum_i = Checksum_{i-1} xor P_i  */
810         xor RAB2, (0 * 8)(RX2);
811         xor RCD2, (1 * 8)(RX2);
812         /* PX_i = P_i xor Offset_i */
813         xorq RT0, RAB2;
814         xorq RT1, RCD2;
815
816         /* Store offset */
817         movq RT0, (0 * 8)(RX1);
818         movq RT1, (1 * 8)(RX1);
819
820         /* CX_i = ENCIPHER(K, PX_i)  */
821         call __twofish_enc_blk3;
822
823         movq (6 * 8)(%rsp), RX1; /*dst*/
824
825         /* C_i = CX_i xor Offset_i  */
826         xorq RCD0, (0 * 8)(RX1);
827         xorq RAB0, (1 * 8)(RX1);
828         xorq RCD1, (2 * 8)(RX1);
829         xorq RAB1, (3 * 8)(RX1);
830         xorq RCD2, (4 * 8)(RX1);
831         xorq RAB2, (5 * 8)(RX1);
832
833         movq (0 * 8)(%rsp), %rbp;
834         movq (1 * 8)(%rsp), %rbx;
835         movq (2 * 8)(%rsp), %r12;
836         movq (3 * 8)(%rsp), %r13;
837         movq (4 * 8)(%rsp), %r14;
838         movq (5 * 8)(%rsp), %r15;
839         addq $(8 * 8), %rsp;
840
841         ret;
842 ELF(.size _gcry_twofish_amd64_ocb_enc,.-_gcry_twofish_amd64_ocb_enc;)
843
844 .align 8
845 .globl _gcry_twofish_amd64_ocb_dec
846 ELF(.type   _gcry_twofish_amd64_ocb_dec,@function;)
847 _gcry_twofish_amd64_ocb_dec:
848         /* input:
849          *      %rdi: ctx, CTX
850          *      %rsi: dst (3 blocks)
851          *      %rdx: src (3 blocks)
852          *      %rcx: offset
853          *      %r8 : checksum
854          *      %r9 : L pointers (void *L[3])
855          */
856         subq $(8 * 8), %rsp;
857         movq %rbp, (0 * 8)(%rsp);
858         movq %rbx, (1 * 8)(%rsp);
859         movq %r12, (2 * 8)(%rsp);
860         movq %r13, (3 * 8)(%rsp);
861         movq %r14, (4 * 8)(%rsp);
862         movq %r15, (5 * 8)(%rsp);
863
864         movq %rsi, (6 * 8)(%rsp);
865         movq %r8,  (7 * 8)(%rsp);
866         movq %rdx, RX0;
867         movq %rcx, RX1;
868         movq %r9, RY0;
869         movq %rsi, RY1;
870
871         /* Load offset */
872         movq (0 * 8)(RX1), RT0;
873         movq (1 * 8)(RX1), RT1;
874
875         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
876         movq (RY0), RY2;
877         xorq (0 * 8)(RY2), RT0;
878         xorq (1 * 8)(RY2), RT1;
879         movq (0 * 8)(RX0), RAB0;
880         movq (1 * 8)(RX0), RCD0;
881         /* Store Offset_i */
882         movq RT0, (0 * 8)(RY1);
883         movq RT1, (1 * 8)(RY1);
884         /* CX_i = C_i xor Offset_i */
885         xorq RT0, RAB0;
886         xorq RT1, RCD0;
887
888         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
889         movq 8(RY0), RY2;
890         xorq (0 * 8)(RY2), RT0;
891         xorq (1 * 8)(RY2), RT1;
892         movq (2 * 8)(RX0), RAB1;
893         movq (3 * 8)(RX0), RCD1;
894         /* Store Offset_i */
895         movq RT0, (2 * 8)(RY1);
896         movq RT1, (3 * 8)(RY1);
897         /* PX_i = P_i xor Offset_i */
898         xorq RT0, RAB1;
899         xorq RT1, RCD1;
900
901         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
902         movq 16(RY0), RY2;
903         xorq (0 * 8)(RY2), RT0;
904         xorq (1 * 8)(RY2), RT1;
905         movq (4 * 8)(RX0), RAB2;
906         movq (5 * 8)(RX0), RCD2;
907         /* Store Offset_i */
908         movq RT0, (4 * 8)(RY1);
909         movq RT1, (5 * 8)(RY1);
910         /* PX_i = P_i xor Offset_i */
911         xorq RT0, RAB2;
912         xorq RT1, RCD2;
913
914         /* Store offset */
915         movq RT0, (0 * 8)(RX1);
916         movq RT1, (1 * 8)(RX1);
917
918         /* PX_i = DECIPHER(K, CX_i)  */
919         call __twofish_dec_blk3;
920
921         movq (7 * 8)(%rsp), RX2; /*checksum*/
922         movq (6 * 8)(%rsp), RX1; /*dst*/
923
924         /* Load checksum */
925         movq (0 * 8)(RX2), RT0;
926         movq (1 * 8)(RX2), RT1;
927
928         /* P_i = PX_i xor Offset_i  */
929         xorq RCD0, (0 * 8)(RX1);
930         xorq RAB0, (1 * 8)(RX1);
931         xorq RCD1, (2 * 8)(RX1);
932         xorq RAB1, (3 * 8)(RX1);
933         xorq RCD2, (4 * 8)(RX1);
934         xorq RAB2, (5 * 8)(RX1);
935
936         /* Checksum_i = Checksum_{i-1} xor P_i  */
937         xorq (0 * 8)(RX1), RT0;
938         xorq (1 * 8)(RX1), RT1;
939         xorq (2 * 8)(RX1), RT0;
940         xorq (3 * 8)(RX1), RT1;
941         xorq (4 * 8)(RX1), RT0;
942         xorq (5 * 8)(RX1), RT1;
943
944         /* Store checksum */
945         movq RT0, (0 * 8)(RX2);
946         movq RT1, (1 * 8)(RX2);
947
948         movq (0 * 8)(%rsp), %rbp;
949         movq (1 * 8)(%rsp), %rbx;
950         movq (2 * 8)(%rsp), %r12;
951         movq (3 * 8)(%rsp), %r13;
952         movq (4 * 8)(%rsp), %r14;
953         movq (5 * 8)(%rsp), %r15;
954         addq $(8 * 8), %rsp;
955
956         ret;
957 ELF(.size _gcry_twofish_amd64_ocb_dec,.-_gcry_twofish_amd64_ocb_dec;)
958
959 .align 8
960 .globl _gcry_twofish_amd64_ocb_auth
961 ELF(.type   _gcry_twofish_amd64_ocb_auth,@function;)
962 _gcry_twofish_amd64_ocb_auth:
963         /* input:
964          *      %rdi: ctx, CTX
965          *      %rsi: abuf (3 blocks)
966          *      %rdx: offset
967          *      %rcx: checksum
968          *      %r8 : L pointers (void *L[3])
969          */
970         subq $(8 * 8), %rsp;
971         movq %rbp, (0 * 8)(%rsp);
972         movq %rbx, (1 * 8)(%rsp);
973         movq %r12, (2 * 8)(%rsp);
974         movq %r13, (3 * 8)(%rsp);
975         movq %r14, (4 * 8)(%rsp);
976         movq %r15, (5 * 8)(%rsp);
977
978         movq %rcx, (6 * 8)(%rsp);
979         movq %rsi, RX0;
980         movq %rdx, RX1;
981         movq %r8, RY0;
982
983         /* Load offset */
984         movq (0 * 8)(RX1), RT0;
985         movq (1 * 8)(RX1), RT1;
986
987         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
988         movq (RY0), RY2;
989         xorq (0 * 8)(RY2), RT0;
990         xorq (1 * 8)(RY2), RT1;
991         movq (0 * 8)(RX0), RAB0;
992         movq (1 * 8)(RX0), RCD0;
993         /* PX_i = P_i xor Offset_i */
994         xorq RT0, RAB0;
995         xorq RT1, RCD0;
996
997         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
998         movq 8(RY0), RY2;
999         xorq (0 * 8)(RY2), RT0;
1000         xorq (1 * 8)(RY2), RT1;
1001         movq (2 * 8)(RX0), RAB1;
1002         movq (3 * 8)(RX0), RCD1;
1003         /* PX_i = P_i xor Offset_i */
1004         xorq RT0, RAB1;
1005         xorq RT1, RCD1;
1006
1007         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1008         movq 16(RY0), RY2;
1009         xorq (0 * 8)(RY2), RT0;
1010         xorq (1 * 8)(RY2), RT1;
1011         movq (4 * 8)(RX0), RAB2;
1012         movq (5 * 8)(RX0), RCD2;
1013         /* PX_i = P_i xor Offset_i */
1014         xorq RT0, RAB2;
1015         xorq RT1, RCD2;
1016
1017         /* Store offset */
1018         movq RT0, (0 * 8)(RX1);
1019         movq RT1, (1 * 8)(RX1);
1020
1021         /* C_i = ENCIPHER(K, PX_i)  */
1022         call __twofish_enc_blk3;
1023
1024         movq (6 * 8)(%rsp), RX1; /*checksum*/
1025
1026         /* Checksum_i = C_i xor Checksum_i  */
1027         xorq RCD0, RCD1;
1028         xorq RAB0, RAB1;
1029         xorq RCD1, RCD2;
1030         xorq RAB1, RAB2;
1031         xorq RCD2, (0 * 8)(RX1);
1032         xorq RAB2, (1 * 8)(RX1);
1033
1034         movq (0 * 8)(%rsp), %rbp;
1035         movq (1 * 8)(%rsp), %rbx;
1036         movq (2 * 8)(%rsp), %r12;
1037         movq (3 * 8)(%rsp), %r13;
1038         movq (4 * 8)(%rsp), %r14;
1039         movq (5 * 8)(%rsp), %r15;
1040         addq $(8 * 8), %rsp;
1041
1042         ret;
1043 ELF(.size _gcry_twofish_amd64_ocb_auth,.-_gcry_twofish_amd64_ocb_auth;)
1044
1045 #endif /*USE_TWOFISH*/
1046 #endif /*__x86_64*/