Add PowerPC extra CFLAGS also for chacha20-ppc and crc-ppc
[libgcrypt.git] / cipher / blowfish-amd64.S
1 /* blowfish-amd64.S  -  AMD64 assembly implementation of Blowfish 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(USE_BLOWFISH) && \
24     (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
25      defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
26
27 #include "asm-common-amd64.h"
28
29 .text
30
31 /* structure of BLOWFISH_context: */
32 #define s0      0
33 #define s1      ((s0) + 256 * 4)
34 #define s2      ((s1) + 256 * 4)
35 #define s3      ((s2) + 256 * 4)
36 #define p       ((s3) + 256 * 4)
37
38 /* register macros */
39 #define CTX %rdi
40 #define RIO %rsi
41
42 #define RX0 %rax
43 #define RX1 %rbx
44 #define RX2 %rcx
45 #define RX3 %rdx
46
47 #define RX0d %eax
48 #define RX1d %ebx
49 #define RX2d %ecx
50 #define RX3d %edx
51
52 #define RX0bl %al
53 #define RX1bl %bl
54 #define RX2bl %cl
55 #define RX3bl %dl
56
57 #define RX0bh %ah
58 #define RX1bh %bh
59 #define RX2bh %ch
60 #define RX3bh %dh
61
62 #define RT0 %rbp
63 #define RT1 %rsi
64 #define RT2 %r8
65 #define RT3 %r9
66
67 #define RT0d %ebp
68 #define RT1d %esi
69 #define RT2d %r8d
70 #define RT3d %r9d
71
72 #define RKEY %r10
73
74 /***********************************************************************
75  * 1-way blowfish
76  ***********************************************************************/
77 #define F() \
78         movzbl RX0bh,           RT1d; \
79         movzbl RX0bl,           RT3d; \
80         rorq $16,               RX0; \
81         movzbl RX0bh,           RT0d; \
82         movzbl RX0bl,           RT2d; \
83         rorq $16,               RX0; \
84         movl s0(CTX,RT0,4),     RT0d; \
85         addl s1(CTX,RT2,4),     RT0d; \
86         xorl s2(CTX,RT1,4),     RT0d; \
87         addl s3(CTX,RT3,4),     RT0d; \
88         xorq RT0,               RX0;
89
90 #define load_roundkey_enc(n) \
91         movq p+4*(n)(CTX),      RX3;
92
93 #define add_roundkey_enc() \
94         xorq RX3,               RX0;
95
96 #define round_enc(n) \
97         add_roundkey_enc(); \
98         load_roundkey_enc(n); \
99         \
100         F(); \
101         F();
102
103 #define load_roundkey_dec(n) \
104         movq p+4*(n-1)(CTX),    RX3; \
105         rorq $32,               RX3;
106
107 #define add_roundkey_dec() \
108         xorq RX3,               RX0;
109
110 #define round_dec(n) \
111         add_roundkey_dec(); \
112         load_roundkey_dec(n); \
113         \
114         F(); \
115         F();
116
117 #define read_block() \
118         movq (RIO),             RX0; \
119         rorq $32,               RX0; \
120         bswapq                  RX0;
121
122 #define write_block() \
123         bswapq                  RX0; \
124         movq RX0,               (RIO);
125
126 .align 8
127 ELF(.type   __blowfish_enc_blk1,@function;)
128
129 __blowfish_enc_blk1:
130         /* input:
131          *      %rdi: ctx, CTX
132          *      RX0: input plaintext block
133          * output:
134          *      RX0: output plaintext block
135          */
136         CFI_STARTPROC();
137         movq %rbp, %r11;
138         CFI_REGISTER(%rbp, %r11);
139
140         load_roundkey_enc(0);
141         round_enc(2);
142         round_enc(4);
143         round_enc(6);
144         round_enc(8);
145         round_enc(10);
146         round_enc(12);
147         round_enc(14);
148         round_enc(16);
149         add_roundkey_enc();
150
151         movq %r11, %rbp;
152         CFI_RESTORE(%rbp)
153
154         ret;
155         CFI_ENDPROC();
156 ELF(.size __blowfish_enc_blk1,.-__blowfish_enc_blk1;)
157
158 .align 8
159 .globl  _gcry_blowfish_amd64_do_encrypt
160 ELF(.type   _gcry_blowfish_amd64_do_encrypt,@function;)
161
162 _gcry_blowfish_amd64_do_encrypt:
163         /* input:
164          *      %rdi: ctx, CTX
165          *      %rsi: u32 *ret_xl
166          *      %rdx: u32 *ret_xr
167          */
168         CFI_STARTPROC();
169         ENTER_SYSV_FUNC_PARAMS_0_4
170
171         movl (%rdx), RX0d;
172         shlq $32, RX0;
173         movl (%rsi), RT3d;
174         movq %rdx, %r10;
175         orq RT3, RX0;
176         movq %rsi, RX2;
177
178         call __blowfish_enc_blk1;
179
180         movl RX0d, (%r10);
181         shrq $32, RX0;
182         movl RX0d, (RX2);
183
184         EXIT_SYSV_FUNC
185         ret;
186         CFI_ENDPROC();
187 ELF(.size _gcry_blowfish_amd64_do_encrypt,.-_gcry_blowfish_amd64_do_encrypt;)
188
189 .align 8
190 .globl  _gcry_blowfish_amd64_encrypt_block
191 ELF(.type   _gcry_blowfish_amd64_encrypt_block,@function;)
192
193 _gcry_blowfish_amd64_encrypt_block:
194         /* input:
195          *      %rdi: ctx, CTX
196          *      %rsi: dst
197          *      %rdx: src
198          */
199         CFI_STARTPROC();
200         ENTER_SYSV_FUNC_PARAMS_0_4
201
202         movq %rsi, %r10;
203
204         movq %rdx, RIO;
205         read_block();
206
207         call __blowfish_enc_blk1;
208
209         movq %r10, RIO;
210         write_block();
211
212         EXIT_SYSV_FUNC
213         ret;
214         CFI_ENDPROC();
215 ELF(.size _gcry_blowfish_amd64_encrypt_block,.-_gcry_blowfish_amd64_encrypt_block;)
216
217 .align 8
218 .globl  _gcry_blowfish_amd64_decrypt_block
219 ELF(.type   _gcry_blowfish_amd64_decrypt_block,@function;)
220
221 _gcry_blowfish_amd64_decrypt_block:
222         /* input:
223          *      %rdi: ctx, CTX
224          *      %rsi: dst
225          *      %rdx: src
226          */
227         CFI_STARTPROC();
228         ENTER_SYSV_FUNC_PARAMS_0_4
229
230         movq %rbp, %r11;
231         CFI_REGISTER(%rbp, %r11);
232
233         movq %rsi, %r10;
234         movq %rdx, RIO;
235
236         read_block();
237
238         load_roundkey_dec(17);
239         round_dec(15);
240         round_dec(13);
241         round_dec(11);
242         round_dec(9);
243         round_dec(7);
244         round_dec(5);
245         round_dec(3);
246         round_dec(1);
247         add_roundkey_dec();
248
249         movq %r10, RIO;
250         write_block();
251
252         movq %r11, %rbp;
253         CFI_RESTORE(%rbp);
254
255         EXIT_SYSV_FUNC
256         ret;
257         CFI_ENDPROC();
258 ELF(.size _gcry_blowfish_amd64_decrypt_block,.-_gcry_blowfish_amd64_decrypt_block;)
259
260 /**********************************************************************
261   4-way blowfish, four blocks parallel
262  **********************************************************************/
263 #define F4(x) \
264         movzbl x ## bh,         RT1d; \
265         movzbl x ## bl,         RT3d; \
266         rorq $16,               x; \
267         movzbl x ## bh,         RT0d; \
268         movzbl x ## bl,         RT2d; \
269         rorq $16,               x; \
270         movl s0(CTX,RT0,4),     RT0d; \
271         addl s1(CTX,RT2,4),     RT0d; \
272         xorl s2(CTX,RT1,4),     RT0d; \
273         addl s3(CTX,RT3,4),     RT0d; \
274         xorq RT0,               x;
275
276 #define add_preloaded_roundkey4() \
277         xorq RKEY,              RX0; \
278         xorq RKEY,              RX1; \
279         xorq RKEY,              RX2; \
280         xorq RKEY,              RX3;
281
282 #define preload_roundkey_enc(n) \
283         movq p+4*(n)(CTX),      RKEY;
284
285 #define add_roundkey_enc4(n) \
286         add_preloaded_roundkey4(); \
287         preload_roundkey_enc(n + 2);
288
289 #define round_enc4(n) \
290         add_roundkey_enc4(n); \
291         \
292         F4(RX0); \
293         F4(RX1); \
294         F4(RX2); \
295         F4(RX3); \
296         \
297         F4(RX0); \
298         F4(RX1); \
299         F4(RX2); \
300         F4(RX3);
301
302 #define preload_roundkey_dec(n) \
303         movq p+4*((n)-1)(CTX),  RKEY; \
304         rorq $32,               RKEY;
305
306 #define add_roundkey_dec4(n) \
307         add_preloaded_roundkey4(); \
308         preload_roundkey_dec(n - 2);
309
310 #define round_dec4(n) \
311         add_roundkey_dec4(n); \
312         \
313         F4(RX0); \
314         F4(RX1); \
315         F4(RX2); \
316         F4(RX3); \
317         \
318         F4(RX0); \
319         F4(RX1); \
320         F4(RX2); \
321         F4(RX3);
322
323 #define inbswap_block4() \
324         rorq $32,               RX0; \
325         bswapq                  RX0; \
326         rorq $32,               RX1; \
327         bswapq                  RX1; \
328         rorq $32,               RX2; \
329         bswapq                  RX2; \
330         rorq $32,               RX3; \
331         bswapq                  RX3;
332
333 #define inctrswap_block4() \
334         rorq $32,               RX0; \
335         rorq $32,               RX1; \
336         rorq $32,               RX2; \
337         rorq $32,               RX3;
338
339 #define outbswap_block4() \
340         bswapq                  RX0; \
341         bswapq                  RX1; \
342         bswapq                  RX2; \
343         bswapq                  RX3;
344
345 .align 8
346 ELF(.type   __blowfish_enc_blk4,@function;)
347
348 __blowfish_enc_blk4:
349         /* input:
350          *      %rdi: ctx, CTX
351          *      RX0,RX1,RX2,RX3: four input inbswapped plaintext blocks
352          * output:
353          *      RX0,RX1,RX2,RX3: four output ciphertext blocks
354          */
355         CFI_STARTPROC();
356         preload_roundkey_enc(0);
357
358         round_enc4(0);
359         round_enc4(2);
360         round_enc4(4);
361         round_enc4(6);
362         round_enc4(8);
363         round_enc4(10);
364         round_enc4(12);
365         round_enc4(14);
366         add_preloaded_roundkey4();
367
368         outbswap_block4();
369
370         ret;
371         CFI_ENDPROC();
372 ELF(.size __blowfish_enc_blk4,.-__blowfish_enc_blk4;)
373
374 .align 8
375 ELF(.type   __blowfish_dec_blk4,@function;)
376
377 __blowfish_dec_blk4:
378         /* input:
379          *      %rdi: ctx, CTX
380          *      RX0,RX1,RX2,RX3: four input ciphertext blocks
381          * output:
382          *      RX0,RX1,RX2,RX3: four output plaintext blocks
383          */
384         CFI_STARTPROC();
385         preload_roundkey_dec(17);
386
387         inbswap_block4();
388
389         round_dec4(17);
390         round_dec4(15);
391         round_dec4(13);
392         round_dec4(11);
393         round_dec4(9);
394         round_dec4(7);
395         round_dec4(5);
396         round_dec4(3);
397         add_preloaded_roundkey4();
398
399         outbswap_block4();
400
401         ret;
402         CFI_ENDPROC();
403 ELF(.size __blowfish_dec_blk4,.-__blowfish_dec_blk4;)
404
405 .align 8
406 .globl  _gcry_blowfish_amd64_ctr_enc
407 ELF(.type   _gcry_blowfish_amd64_ctr_enc,@function;)
408 _gcry_blowfish_amd64_ctr_enc:
409         /* input:
410          *      %rdi: ctx, CTX
411          *      %rsi: dst (4 blocks)
412          *      %rdx: src (4 blocks)
413          *      %rcx: iv (big endian, 64bit)
414          */
415         CFI_STARTPROC();
416         ENTER_SYSV_FUNC_PARAMS_0_4
417
418         pushq %rbp;
419         CFI_PUSH(%rbp);
420         pushq %rbx;
421         CFI_PUSH(%rbx);
422         pushq %r12;
423         CFI_PUSH(%r12);
424         pushq %r13;
425         CFI_PUSH(%r13);
426
427         /* %r11-%r13 are not used by __blowfish_enc_blk4 */
428         movq %rcx, %r13; /*iv*/
429         movq %rdx, %r12; /*src*/
430         movq %rsi, %r11; /*dst*/
431
432         /* load IV and byteswap */
433         movq (%r13), RT0;
434         bswapq RT0;
435         movq RT0, RX0;
436
437         /* construct IVs */
438         leaq 1(RT0), RX1;
439         leaq 2(RT0), RX2;
440         leaq 3(RT0), RX3;
441         leaq 4(RT0), RT0;
442         bswapq RT0;
443
444         inctrswap_block4();
445
446         /* store new IV */
447         movq RT0, (%r13);
448
449         call __blowfish_enc_blk4;
450
451         /* XOR key-stream with plaintext */
452         xorq 0 * 8(%r12), RX0;
453         xorq 1 * 8(%r12), RX1;
454         xorq 2 * 8(%r12), RX2;
455         xorq 3 * 8(%r12), RX3;
456         movq RX0, 0 * 8(%r11);
457         movq RX1, 1 * 8(%r11);
458         movq RX2, 2 * 8(%r11);
459         movq RX3, 3 * 8(%r11);
460
461         popq %r13;
462         CFI_POP(%r13);
463         popq %r12;
464         CFI_POP(%r12);
465         popq %rbx;
466         CFI_POP(%rbx);
467         popq %rbp;
468         CFI_POP(%rbp);
469
470         EXIT_SYSV_FUNC
471         ret;
472         CFI_ENDPROC();
473 ELF(.size _gcry_blowfish_amd64_ctr_enc,.-_gcry_blowfish_amd64_ctr_enc;)
474
475 .align 8
476 .globl  _gcry_blowfish_amd64_cbc_dec
477 ELF(.type   _gcry_blowfish_amd64_cbc_dec,@function;)
478 _gcry_blowfish_amd64_cbc_dec:
479         /* input:
480          *      %rdi: ctx, CTX
481          *      %rsi: dst (4 blocks)
482          *      %rdx: src (4 blocks)
483          *      %rcx: iv (64bit)
484          */
485         CFI_STARTPROC();
486         ENTER_SYSV_FUNC_PARAMS_0_4
487
488         pushq %rbp;
489         CFI_PUSH(%rbp);
490         pushq %rbx;
491         CFI_PUSH(%rbx);
492         pushq %r12;
493         CFI_PUSH(%r12);
494         pushq %r13;
495         CFI_PUSH(%r13);
496
497         /* %r11-%r13 are not used by __blowfish_dec_blk4 */
498         movq %rsi, %r11; /*dst*/
499         movq %rdx, %r12; /*src*/
500         movq %rcx, %r13; /*iv*/
501
502         /* load input */
503         movq 0 * 8(%r12), RX0;
504         movq 1 * 8(%r12), RX1;
505         movq 2 * 8(%r12), RX2;
506         movq 3 * 8(%r12), RX3;
507
508         call __blowfish_dec_blk4;
509
510         movq 3 * 8(%r12), RT0;
511         xorq      (%r13), RX0;
512         xorq 0 * 8(%r12), RX1;
513         xorq 1 * 8(%r12), RX2;
514         xorq 2 * 8(%r12), RX3;
515         movq RT0, (%r13); /* store new IV */
516
517         movq RX0, 0 * 8(%r11);
518         movq RX1, 1 * 8(%r11);
519         movq RX2, 2 * 8(%r11);
520         movq RX3, 3 * 8(%r11);
521
522         popq %r13;
523         CFI_POP(%r13);
524         popq %r12;
525         CFI_POP(%r12);
526         popq %rbx;
527         CFI_POP(%rbx);
528         popq %rbp;
529         CFI_POP(%rbp);
530
531         EXIT_SYSV_FUNC
532         ret;
533         CFI_ENDPROC();
534 ELF(.size _gcry_blowfish_amd64_cbc_dec,.-_gcry_blowfish_amd64_cbc_dec;)
535
536 .align 8
537 .globl  _gcry_blowfish_amd64_cfb_dec
538 ELF(.type   _gcry_blowfish_amd64_cfb_dec,@function;)
539 _gcry_blowfish_amd64_cfb_dec:
540         /* input:
541          *      %rdi: ctx, CTX
542          *      %rsi: dst (4 blocks)
543          *      %rdx: src (4 blocks)
544          *      %rcx: iv (64bit)
545          */
546         CFI_STARTPROC();
547         ENTER_SYSV_FUNC_PARAMS_0_4
548
549         pushq %rbp;
550         CFI_PUSH(%rbp);
551         pushq %rbx;
552         CFI_PUSH(%rbx);
553         pushq %r12;
554         CFI_PUSH(%r12);
555         pushq %r13;
556         CFI_PUSH(%r13);
557
558         /* %r11-%r13 are not used by __blowfish_enc_blk4 */
559         movq %rcx, %r13; /*iv*/
560         movq %rdx, %r12; /*src*/
561         movq %rsi, %r11; /*dst*/
562
563         /* Load input */
564         movq (%r13), RX0;
565         movq 0 * 8(%r12), RX1;
566         movq 1 * 8(%r12), RX2;
567         movq 2 * 8(%r12), RX3;
568
569         inbswap_block4();
570
571         /* Update IV */
572         movq 3 * 8(%r12), RT0;
573         movq RT0, (%r13);
574
575         call __blowfish_enc_blk4;
576
577         xorq 0 * 8(%r12), RX0;
578         xorq 1 * 8(%r12), RX1;
579         xorq 2 * 8(%r12), RX2;
580         xorq 3 * 8(%r12), RX3;
581         movq RX0, 0 * 8(%r11);
582         movq RX1, 1 * 8(%r11);
583         movq RX2, 2 * 8(%r11);
584         movq RX3, 3 * 8(%r11);
585
586         popq %r13;
587         CFI_POP(%r13);
588         popq %r12;
589         CFI_POP(%r12);
590         popq %rbx;
591         CFI_POP(%rbx);
592         popq %rbp;
593         CFI_POP(%rbp);
594
595         EXIT_SYSV_FUNC
596         ret;
597         CFI_ENDPROC();
598 ELF(.size _gcry_blowfish_amd64_cfb_dec,.-_gcry_blowfish_amd64_cfb_dec;)
599
600 #endif /*defined(USE_BLOWFISH)*/
601 #endif /*__x86_64*/