build: Fix build with !HAVE_PTHREAD
[libgcrypt.git] / cipher / cast5-amd64.S
1 /* cast5-amd64.S  -  AMD64 assembly implementation of CAST5 cipher
2  *
3  * Copyright (C) 2013 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_CAST5)
25
26 #include "asm-common-amd64.h"
27
28 .text
29
30 .extern _gcry_cast5_s1to4;
31
32 #define s1 0
33 #define s2 (s1 + (4 * 256))
34 #define s3 (s2 + (4 * 256))
35 #define s4 (s3 + (4 * 256))
36
37 /* structure of CAST5_context: */
38 #define Km 0
39 #define Kr (Km + (16 * 4))
40
41 /* register macros */
42 #define CTX %rdi
43 #define RIO %rsi
44 #define RTAB %r8
45
46 #define RLR0 %r9
47 #define RLR1 %r10
48 #define RLR2 %r11
49 #define RLR3 %r12
50
51 #define RLR0d %r9d
52 #define RLR1d %r10d
53 #define RLR2d %r11d
54 #define RLR3d %r12d
55
56 #define RX0 %rax
57 #define RX1 %rbx
58 #define RX2 %rdx
59
60 #define RX0d %eax
61 #define RX1d %ebx
62 #define RX2d %edx
63
64 #define RX0bl %al
65 #define RX1bl %bl
66 #define RX2bl %dl
67
68 #define RX0bh %ah
69 #define RX1bh %bh
70 #define RX2bh %dh
71
72 #define RKR %rcx
73 #define RKRd %ecx
74 #define RKRbl %cl
75
76 #define RT0 %rbp
77 #define RT1 %rsi
78
79 #define RT0d %ebp
80 #define RT1d %esi
81
82 #define RKM0d %r13d
83 #define RKM1d %r14d
84
85 /***********************************************************************
86  * 1-way cast5
87  ***********************************************************************/
88 #define dummy(x)
89
90 #define shr_kr(none) \
91         shrq $8,                        RKR;
92
93 #define F(km, load_next_kr, op0, op1, op2, op3) \
94         op0 ## l RLR0d,                 km ## d; \
95         roll RKRbl,                     km ## d; \
96         rorq $32,                       RLR0; \
97         movzbl km ## bh,                RT0d; \
98         movzbl km ## bl,                RT1d; \
99         roll $16,                       km ## d; \
100         movl s1(RTAB,RT0,4),            RT0d; \
101         op1 ## l s2(RTAB,RT1,4),        RT0d; \
102         load_next_kr(kr_next); \
103         movzbl km ## bh,                RT1d; \
104         movzbl km ## bl,                km ## d; \
105         op2 ## l s3(RTAB,RT1,4),        RT0d; \
106         op3 ## l s4(RTAB,km,4),         RT0d; \
107         xorq RT0,                       RLR0;
108
109 #define F1(km, load_next_kr) \
110         F(##km, load_next_kr, add, xor, sub, add)
111 #define F2(km, load_next_kr) \
112         F(##km, load_next_kr, xor, sub, add, xor)
113 #define F3(km, load_next_kr) \
114         F(##km, load_next_kr, sub, add, xor, sub)
115
116 #define get_round_km(n, km) \
117         movl Km+4*(n)(CTX),             km;
118
119 #define get_round_kr_enc(n) \
120         movq $0x1010101010101010,       RKR; \
121         \
122         /* merge rorl rk and rorl $16 */ \
123         xorq Kr+(n)(CTX),               RKR;
124
125 #define get_round_kr_dec(n) \
126         movq $0x1010101010101010,       RKR; \
127         \
128         /* merge rorl rk and rorl $16 */ \
129         xorq Kr+(n - 7)(CTX),           RKR; \
130         bswapq                          RKR;
131
132 #define round_enc(n, FA, FB, fn1, fn2) \
133         get_round_km(n + 1, RX2d); \
134         FA(RX0, fn1); \
135         get_round_km(n + 2, RX0d); \
136         FB(RX2, fn2);
137
138 #define round_enc_last(n, FXA, FXB) \
139         get_round_km(n + 1, RX2d); \
140         \
141         FXA(RX0, shr_kr); \
142         FXB(RX2, dummy);
143
144 #define round_enc_1(n, FA, FB) \
145         round_enc(n, FA, FB, shr_kr, shr_kr)
146
147 #define round_enc_2(n, FA, FB) \
148         round_enc(n, FA, FB, shr_kr, dummy)
149
150 #define round_dec(n, FA, FB, fn1, fn2) \
151         get_round_km(n - 1, RX2d); \
152         FA(RX0, fn1); \
153         get_round_km(n - 2, RX0d); \
154         FB(RX2, fn2);
155
156 #define round_dec_last(n, FXA, FXB) \
157         get_round_km(n - 1, RX2d); \
158         FXA(RX0, shr_kr); \
159         FXB(RX2, dummy);
160
161 #define round_dec_1(n, FA, FB) \
162         round_dec(n, FA, FB, shr_kr, shr_kr)
163
164 #define round_dec_2(n, FA, FB) \
165         round_dec(n, FA, FB, shr_kr, dummy)
166
167 #define read_block() \
168         movq (RIO),             RLR0; \
169         bswapq                  RLR0;
170
171 #define write_block() \
172         bswapq                  RLR0; \
173         rorq $32,               RLR0; \
174         movq RLR0,              (RIO);
175
176 .align 8
177 .globl _gcry_cast5_amd64_encrypt_block
178 ELF(.type   _gcry_cast5_amd64_encrypt_block,@function;)
179
180 _gcry_cast5_amd64_encrypt_block:
181         /* input:
182          *      %rdi: ctx, CTX
183          *      %rsi: dst
184          *      %rdx: src
185          */
186         CFI_STARTPROC();
187         ENTER_SYSV_FUNC_PARAMS_0_4
188
189         pushq %rbp;
190         CFI_PUSH(%rbp);
191         pushq %rbx;
192         CFI_PUSH(%rbx);
193
194         movq %rsi, %r10;
195
196         GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
197
198         movq %rdx, RIO;
199         read_block();
200
201         get_round_km(0, RX0d);
202         get_round_kr_enc(0);
203         round_enc_1(0, F1, F2);
204         round_enc_1(2, F3, F1);
205         round_enc_1(4, F2, F3);
206         round_enc_2(6, F1, F2);
207         get_round_kr_enc(8);
208         round_enc_1(8, F3, F1);
209         round_enc_1(10, F2, F3);
210         round_enc_1(12, F1, F2);
211         round_enc_last(14, F3, F1);
212
213         movq %r10, RIO;
214         write_block();
215
216         popq %rbx;
217         CFI_POP(%rbx);
218         popq %rbp;
219         CFI_POP(%rbp);
220
221         EXIT_SYSV_FUNC
222         ret;
223         CFI_ENDPROC();
224 ELF(.size _gcry_cast5_amd64_encrypt_block,.-_gcry_cast5_amd64_encrypt_block;)
225
226 .align 8
227 .globl _gcry_cast5_amd64_decrypt_block
228 ELF(.type   _gcry_cast5_amd64_decrypt_block,@function;)
229
230 _gcry_cast5_amd64_decrypt_block:
231         /* input:
232          *      %rdi: ctx, CTX
233          *      %rsi: dst
234          *      %rdx: src
235          */
236         CFI_STARTPROC();
237         ENTER_SYSV_FUNC_PARAMS_0_4
238
239         pushq %rbp;
240         CFI_PUSH(%rbp);
241         pushq %rbx;
242         CFI_PUSH(%rbx);
243
244         movq %rsi, %r10;
245
246         GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
247
248         movq %rdx, RIO;
249         read_block();
250
251         get_round_km(15, RX0d);
252         get_round_kr_dec(15);
253         round_dec_1(15, F1, F3);
254         round_dec_1(13, F2, F1);
255         round_dec_1(11, F3, F2);
256         round_dec_2(9, F1, F3);
257         get_round_kr_dec(7);
258         round_dec_1(7, F2, F1);
259         round_dec_1(5, F3, F2);
260         round_dec_1(3, F1, F3);
261         round_dec_last(1, F2, F1);
262
263         movq %r10, RIO;
264         write_block();
265
266         popq %rbx;
267         CFI_POP(%rbx);
268         popq %rbp;
269         CFI_POP(%rbp);
270
271         EXIT_SYSV_FUNC
272         ret;
273         CFI_ENDPROC();
274 ELF(.size _gcry_cast5_amd64_decrypt_block,.-_gcry_cast5_amd64_decrypt_block;)
275
276 /**********************************************************************
277   4-way cast5, four blocks parallel
278  **********************************************************************/
279 #define F_tail(rlr, rx, op1, op2, op3) \
280         movzbl rx ## bh,                RT0d; \
281         movzbl rx ## bl,                RT1d; \
282         roll $16,                       rx ## d; \
283         movl s1(RTAB,RT0,4),            RT0d; \
284         op1 ## l s2(RTAB,RT1,4),        RT0d; \
285         movzbl rx ## bh,                RT1d; \
286         movzbl rx ## bl,                rx ## d; \
287         op2 ## l s3(RTAB,RT1,4),        RT0d; \
288         op3 ## l s4(RTAB,rx,4),         RT0d; \
289         xorq RT0,                       rlr;
290
291 #define F4(km, load_next_kr, op0, op1, op2, op3) \
292         movl km,                        RX0d; \
293         op0 ## l RLR0d,                 RX0d; \
294         roll RKRbl,                     RX0d; \
295         rorq $32,                       RLR0; \
296         \
297         movl km,                        RX1d; \
298         op0 ## l RLR1d,                 RX1d; \
299         roll RKRbl,                     RX1d; \
300         rorq $32,                       RLR1; \
301         \
302         movl km,                        RX2d; \
303         op0 ## l RLR2d,                 RX2d; \
304         roll RKRbl,                     RX2d; \
305         rorq $32,                       RLR2; \
306         \
307         F_tail(RLR0, RX0, op1, op2, op3); \
308         F_tail(RLR1, RX1, op1, op2, op3); \
309         F_tail(RLR2, RX2, op1, op2, op3); \
310         \
311         movl km,                        RX0d; \
312         op0 ## l RLR3d,                 RX0d; \
313         roll RKRbl,                     RX0d; \
314         load_next_kr();                 \
315         rorq $32,                       RLR3; \
316         \
317         F_tail(RLR3, RX0, op1, op2, op3);
318
319 #define F4_1(km, load_next_kr) \
320         F4(km, load_next_kr, add, xor, sub, add)
321 #define F4_2(km, load_next_kr) \
322         F4(km, load_next_kr, xor, sub, add, xor)
323 #define F4_3(km, load_next_kr) \
324         F4(km, load_next_kr, sub, add, xor, sub)
325
326 #define round_enc4(n, FA, FB, fn1, fn2) \
327         get_round_km(n + 1, RKM1d); \
328         FA(RKM0d, fn1); \
329         get_round_km(n + 2, RKM0d); \
330         FB(RKM1d, fn2);
331
332 #define round_enc_last4(n, FXA, FXB) \
333         get_round_km(n + 1, RKM1d); \
334         FXA(RKM0d, shr_kr); \
335         FXB(RKM1d, dummy);
336
337 #define round_enc4_1(n, FA, FB) \
338         round_enc4(n, FA, FB, shr_kr, shr_kr);
339
340 #define round_enc4_2(n, FA, FB) \
341         round_enc4(n, FA, FB, shr_kr, dummy);
342
343 #define round_dec4(n, FA, FB, fn1, fn2) \
344         get_round_km(n - 1, RKM1d); \
345         FA(RKM0d, fn1); \
346         get_round_km(n - 2, RKM0d); \
347         FB(RKM1d, fn2);
348
349 #define round_dec_last4(n, FXA, FXB) \
350         get_round_km(n - 1, RKM1d); \
351         FXA(RKM0d, shr_kr); \
352         FXB(RKM1d, dummy);
353
354 #define round_dec4_1(n, FA, FB) \
355         round_dec4(n, FA, FB, shr_kr, shr_kr);
356
357 #define round_dec4_2(n, FA, FB) \
358         round_dec4(n, FA, FB, shr_kr, dummy);
359
360 #define inbswap_block4(a, b, c, d) \
361         bswapq                  a; \
362         bswapq                  b; \
363         bswapq                  c; \
364         bswapq                  d;
365
366 #define outbswap_block4(a, b, c, d) \
367         bswapq                  a; \
368         bswapq                  b; \
369         bswapq                  c; \
370         bswapq                  d; \
371         rorq $32,               a; \
372         rorq $32,               b; \
373         rorq $32,               c; \
374         rorq $32,               d;
375
376 .align 8
377 ELF(.type   __cast5_enc_blk4,@function;)
378
379 __cast5_enc_blk4:
380         /* input:
381          *      %rdi: ctx, CTX
382          *      RLR0,RLR1,RLR2,RLR3: four input plaintext blocks
383          * output:
384          *      RLR0,RLR1,RLR2,RLR3: four output ciphertext blocks
385          */
386         CFI_STARTPROC();
387         GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
388
389         get_round_km(0, RKM0d);
390         get_round_kr_enc(0);
391         round_enc4_1(0, F4_1, F4_2);
392         round_enc4_1(2, F4_3, F4_1);
393         round_enc4_1(4, F4_2, F4_3);
394         round_enc4_2(6, F4_1, F4_2);
395         get_round_kr_enc(8);
396         round_enc4_1(8, F4_3, F4_1);
397         round_enc4_1(10, F4_2, F4_3);
398         round_enc4_1(12, F4_1, F4_2);
399         round_enc_last4(14, F4_3, F4_1);
400
401         outbswap_block4(RLR0, RLR1, RLR2, RLR3);
402         ret;
403         CFI_ENDPROC();
404 ELF(.size __cast5_enc_blk4,.-__cast5_enc_blk4;)
405
406 .align 8
407 ELF(.type   __cast5_dec_blk4,@function;)
408
409 __cast5_dec_blk4:
410         /* input:
411          *      %rdi: ctx, CTX
412          *      RLR0,RLR1,RLR2,RLR3: four input ciphertext blocks
413          * output:
414          *      RLR0,RLR1,RLR2,RLR3: four output plaintext blocks
415          */
416         CFI_STARTPROC();
417         GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
418
419         inbswap_block4(RLR0, RLR1, RLR2, RLR3);
420
421         get_round_km(15, RKM0d);
422         get_round_kr_dec(15);
423         round_dec4_1(15, F4_1, F4_3);
424         round_dec4_1(13, F4_2, F4_1);
425         round_dec4_1(11, F4_3, F4_2);
426         round_dec4_2(9, F4_1, F4_3);
427         get_round_kr_dec(7);
428         round_dec4_1(7, F4_2, F4_1);
429         round_dec4_1(5, F4_3, F4_2);
430         round_dec4_1(3, F4_1, F4_3);
431         round_dec_last4(1, F4_2, F4_1);
432
433         outbswap_block4(RLR0, RLR1, RLR2, RLR3);
434         CFI_ENDPROC();
435         ret;
436 ELF(.size __cast5_dec_blk4,.-__cast5_dec_blk4;)
437
438 .align 8
439 .globl _gcry_cast5_amd64_ctr_enc
440 ELF(.type   _gcry_cast5_amd64_ctr_enc,@function;)
441 _gcry_cast5_amd64_ctr_enc:
442         /* input:
443          *      %rdi: ctx, CTX
444          *      %rsi: dst (4 blocks)
445          *      %rdx: src (4 blocks)
446          *      %rcx: iv (big endian, 64bit)
447          */
448         CFI_STARTPROC();
449         ENTER_SYSV_FUNC_PARAMS_0_4
450
451         pushq %rbp;
452         CFI_PUSH(%rbp);
453         pushq %rbx;
454         CFI_PUSH(%rbx);
455         pushq %r12;
456         CFI_PUSH(%r12);
457         pushq %r13;
458         CFI_PUSH(%r13);
459         pushq %r14;
460         CFI_PUSH(%r14);
461
462         pushq %rsi;
463         CFI_PUSH(%rsi);
464         pushq %rdx;
465         CFI_PUSH(%rdx);
466
467         /* load IV and byteswap */
468         movq (%rcx), RX0;
469         bswapq RX0;
470         movq RX0, RLR0;
471
472         /* construct IVs */
473         leaq 1(RX0), RLR1;
474         leaq 2(RX0), RLR2;
475         leaq 3(RX0), RLR3;
476         leaq 4(RX0), RX0;
477         bswapq RX0;
478
479         /* store new IV */
480         movq RX0, (%rcx);
481
482         call __cast5_enc_blk4;
483
484         popq %r14; /*src*/
485         CFI_POP_TMP_REG();
486         popq %r13; /*dst*/
487         CFI_POP_TMP_REG();
488
489         /* XOR key-stream with plaintext */
490         xorq 0 * 8(%r14), RLR0;
491         xorq 1 * 8(%r14), RLR1;
492         xorq 2 * 8(%r14), RLR2;
493         xorq 3 * 8(%r14), RLR3;
494         movq RLR0, 0 * 8(%r13);
495         movq RLR1, 1 * 8(%r13);
496         movq RLR2, 2 * 8(%r13);
497         movq RLR3, 3 * 8(%r13);
498
499         popq %r14;
500         CFI_POP(%r14);
501         popq %r13;
502         CFI_POP(%r13);
503         popq %r12;
504         CFI_POP(%r12);
505         popq %rbx;
506         CFI_POP(%rbx);
507         popq %rbp;
508         CFI_POP(%rbp);
509
510         EXIT_SYSV_FUNC
511         ret
512         CFI_ENDPROC();
513 ELF(.size _gcry_cast5_amd64_ctr_enc,.-_gcry_cast5_amd64_ctr_enc;)
514
515 .align 8
516 .globl _gcry_cast5_amd64_cbc_dec
517 ELF(.type   _gcry_cast5_amd64_cbc_dec,@function;)
518 _gcry_cast5_amd64_cbc_dec:
519         /* input:
520          *      %rdi: ctx, CTX
521          *      %rsi: dst (4 blocks)
522          *      %rdx: src (4 blocks)
523          *      %rcx: iv (64bit)
524          */
525         CFI_STARTPROC();
526         ENTER_SYSV_FUNC_PARAMS_0_4
527
528         pushq %rbp;
529         CFI_PUSH(%rbp);
530         pushq %rbx;
531         CFI_PUSH(%rbx);
532         pushq %r12;
533         CFI_PUSH(%r12);
534         pushq %r13;
535         CFI_PUSH(%r13);
536         pushq %r14;
537         CFI_PUSH(%r14);
538
539         pushq %rcx;
540         CFI_PUSH(%rcx);
541         pushq %rsi;
542         CFI_PUSH(%rsi);
543         pushq %rdx;
544         CFI_PUSH(%rdx);
545
546         /* load input */
547         movq 0 * 8(%rdx), RLR0;
548         movq 1 * 8(%rdx), RLR1;
549         movq 2 * 8(%rdx), RLR2;
550         movq 3 * 8(%rdx), RLR3;
551
552         call __cast5_dec_blk4;
553
554         popq RX0; /*src*/
555         CFI_POP_TMP_REG();
556         popq RX1; /*dst*/
557         CFI_POP_TMP_REG();
558         popq RX2; /*iv*/
559         CFI_POP_TMP_REG();
560
561         movq 3 * 8(RX0), %r14;
562         xorq      (RX2), RLR0;
563         xorq 0 * 8(RX0), RLR1;
564         xorq 1 * 8(RX0), RLR2;
565         xorq 2 * 8(RX0), RLR3;
566         movq %r14, (RX2); /* store new IV */
567
568         movq RLR0, 0 * 8(RX1);
569         movq RLR1, 1 * 8(RX1);
570         movq RLR2, 2 * 8(RX1);
571         movq RLR3, 3 * 8(RX1);
572
573         popq %r14;
574         CFI_POP(%r14);
575         popq %r13;
576         CFI_POP(%r13);
577         popq %r12;
578         CFI_POP(%r12);
579         popq %rbx;
580         CFI_POP(%rbx);
581         popq %rbp;
582         CFI_POP(%rbp);
583
584         EXIT_SYSV_FUNC
585         ret;
586         CFI_ENDPROC();
587 ELF(.size _gcry_cast5_amd64_cbc_dec,.-_gcry_cast5_amd64_cbc_dec;)
588
589 .align 8
590 .globl _gcry_cast5_amd64_cfb_dec
591 ELF(.type   _gcry_cast5_amd64_cfb_dec,@function;)
592 _gcry_cast5_amd64_cfb_dec:
593         /* input:
594          *      %rdi: ctx, CTX
595          *      %rsi: dst (4 blocks)
596          *      %rdx: src (4 blocks)
597          *      %rcx: iv (64bit)
598          */
599         CFI_STARTPROC();
600         ENTER_SYSV_FUNC_PARAMS_0_4
601
602         pushq %rbp;
603         CFI_PUSH(%rbp);
604         pushq %rbx;
605         CFI_PUSH(%rbx);
606         pushq %r12;
607         CFI_PUSH(%r12);
608         pushq %r13;
609         CFI_PUSH(%r13);
610         pushq %r14;
611         CFI_PUSH(%r14);
612
613         pushq %rsi;
614         CFI_PUSH(%rsi);
615         pushq %rdx;
616         CFI_PUSH(%rdx);
617
618         /* Load input */
619         movq (%rcx), RLR0;
620         movq 0 * 8(%rdx), RLR1;
621         movq 1 * 8(%rdx), RLR2;
622         movq 2 * 8(%rdx), RLR3;
623
624         inbswap_block4(RLR0, RLR1, RLR2, RLR3);
625
626         /* Update IV */
627         movq 3 * 8(%rdx), %rdx;
628         movq %rdx, (%rcx);
629
630         call __cast5_enc_blk4;
631
632         popq %rdx; /*src*/
633         CFI_POP_TMP_REG();
634         popq %rcx; /*dst*/
635         CFI_POP_TMP_REG();
636
637         xorq 0 * 8(%rdx), RLR0;
638         xorq 1 * 8(%rdx), RLR1;
639         xorq 2 * 8(%rdx), RLR2;
640         xorq 3 * 8(%rdx), RLR3;
641         movq RLR0, 0 * 8(%rcx);
642         movq RLR1, 1 * 8(%rcx);
643         movq RLR2, 2 * 8(%rcx);
644         movq RLR3, 3 * 8(%rcx);
645
646         popq %r14;
647         CFI_POP(%r14);
648         popq %r13;
649         CFI_POP(%r13);
650         popq %r12;
651         CFI_POP(%r12);
652         popq %rbx;
653         CFI_POP(%rbx);
654         popq %rbp;
655         CFI_POP(%rbp);
656
657         EXIT_SYSV_FUNC
658         ret;
659         CFI_ENDPROC();
660 ELF(.size _gcry_cast5_amd64_cfb_dec,.-_gcry_cast5_amd64_cfb_dec;)
661
662 #endif /*defined(USE_CAST5)*/
663 #endif /*__x86_64*/