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