More optimized CRC implementations
[libgcrypt.git] / cipher / rijndael-amd64.S
1 /* rinjdael-amd64.S  -  AMD64 assembly implementation of AES 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_AES)
25
26 #ifdef __PIC__
27 #  define RIP (%rip)
28 #else
29 #  define RIP
30 #endif
31
32 #ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
33 # define ELF(...) __VA_ARGS__
34 #else
35 # define ELF(...) /*_*/
36 #endif
37
38 .text
39
40 /* table macros */
41 #define E0      (0)
42 #define Es0     (1)
43 #define Esize   4
44 #define Essize  4
45
46 #define D0      (0)
47 #define Ds0     (4 * 256)
48 #define Dsize   4
49 #define Dssize  1
50
51 /* register macros */
52 #define CTX     %rdi
53 #define RTAB    %r12
54
55 #define RA      %rax
56 #define RB      %rbx
57 #define RC      %rcx
58 #define RD      %rdx
59
60 #define RAd     %eax
61 #define RBd     %ebx
62 #define RCd     %ecx
63 #define RDd     %edx
64
65 #define RAbl    %al
66 #define RBbl    %bl
67 #define RCbl    %cl
68 #define RDbl    %dl
69
70 #define RAbh    %ah
71 #define RBbh    %bh
72 #define RCbh    %ch
73 #define RDbh    %dh
74
75 #define RNA     %r8
76 #define RNB     %r9
77 #define RNC     %r10
78 #define RND     %r11
79
80 #define RNAd    %r8d
81 #define RNBd    %r9d
82 #define RNCd    %r10d
83 #define RNDd    %r11d
84
85 #define RT0     %rbp
86 #define RT1     %rsi
87
88 #define RT0d    %ebp
89 #define RT1d    %esi
90
91 /* helper macros */
92 #define do16bit(op, source, tablemul, table1, dest1, table2, dest2, t0, t1) \
93         movzbl source ## bl,                    t0 ## d; \
94         movzbl source ## bh,                    t1 ## d; \
95         op ## l table1(RTAB,t0,tablemul),       dest1 ## d; \
96         op ## l table2(RTAB,t1,tablemul),       dest2 ## d;
97
98 #define do16bit_shr(shf, op, source, tablemul, table1, dest1, table2, dest2, t0, t1) \
99         movzbl source ## bl,                    t0 ## d; \
100         movzbl source ## bh,                    t1 ## d; \
101         shrl $(shf),                            source ## d; \
102         op ## l table1(RTAB,t0,tablemul),       dest1 ## d; \
103         op ## l table2(RTAB,t1,tablemul),       dest2 ## d;
104
105 #define last_do16bit(op, source, tablemul, table1, dest1, table2, dest2, t0, t1) \
106         movzbl source ## bl,                    t0 ## d; \
107         movzbl source ## bh,                    t1 ## d; \
108         movzbl table1(RTAB,t0,tablemul),        t0 ## d; \
109         movzbl table2(RTAB,t1,tablemul),        t1 ## d; \
110         op ## l t0 ## d,                        dest1 ## d; \
111         op ## l t1 ## d,                        dest2 ## d;
112
113 #define last_do16bit_shr(shf, op, source, tablemul, table1, dest1, table2, dest2, t0, t1) \
114         movzbl source ## bl,                    t0 ## d; \
115         movzbl source ## bh,                    t1 ## d; \
116         shrl $(shf),                            source ## d; \
117         movzbl table1(RTAB,t0,tablemul),        t0 ## d; \
118         movzbl table2(RTAB,t1,tablemul),        t1 ## d; \
119         op ## l t0 ## d,                        dest1 ## d; \
120         op ## l t1 ## d,                        dest2 ## d;
121
122 /***********************************************************************
123  * AMD64 assembly implementation of the AES cipher
124  ***********************************************************************/
125 #define addroundkey(round, ra, rb, rc, rd) \
126         xorl (((round) * 16) + 0 * 4)(CTX), ra ## d; \
127         xorl (((round) * 16) + 1 * 4)(CTX), rb ## d; \
128         xorl (((round) * 16) + 2 * 4)(CTX), rc ## d; \
129         xorl (((round) * 16) + 3 * 4)(CTX), rd ## d;
130
131 #define do_encround(next_r) \
132         do16bit_shr(16, mov, RA, Esize, E0, RNA, E0, RND, RT0, RT1); \
133         do16bit(        mov, RA, Esize, E0, RNC, E0, RNB, RT0, RT1); \
134         movl (((next_r) * 16) + 0 * 4)(CTX), RAd; \
135         roll $8, RNDd; \
136         xorl RNAd, RAd; \
137         roll $8, RNCd; \
138         roll $8, RNBd; \
139         roll $8, RAd; \
140         \
141         do16bit_shr(16, xor, RD, Esize, E0, RND, E0, RNC, RT0, RT1); \
142         do16bit(        xor, RD, Esize, E0, RNB, E0, RA,  RT0, RT1); \
143         movl (((next_r) * 16) + 3 * 4)(CTX), RDd; \
144         roll $8, RNCd; \
145         xorl RNDd, RDd; \
146         roll $8, RNBd; \
147         roll $8, RAd; \
148         roll $8, RDd; \
149         \
150         do16bit_shr(16, xor, RC, Esize, E0, RNC, E0, RNB, RT0, RT1); \
151         do16bit(        xor, RC, Esize, E0, RA,  E0, RD,  RT0, RT1); \
152         movl (((next_r) * 16) + 2 * 4)(CTX), RCd; \
153         roll $8, RNBd; \
154         xorl RNCd, RCd; \
155         roll $8, RAd; \
156         roll $8, RDd; \
157         roll $8, RCd; \
158         \
159         do16bit_shr(16, xor, RB, Esize, E0, RNB, E0, RA,  RT0, RT1); \
160         do16bit(        xor, RB, Esize, E0, RD,  E0, RC,  RT0, RT1); \
161         movl (((next_r) * 16) + 1 * 4)(CTX), RBd; \
162         roll $8, RAd; \
163         xorl RNBd, RBd; \
164         roll $16, RDd; \
165         roll $24, RCd;
166
167 #define do_lastencround(next_r) \
168         do16bit_shr(16, movzb, RA, Essize, Es0, RNA, Es0, RND, RT0, RT1); \
169         do16bit(        movzb, RA, Essize, Es0, RNC, Es0, RNB, RT0, RT1); \
170         movl (((next_r) * 16) + 0 * 4)(CTX), RAd; \
171         roll $8, RNDd; \
172         xorl RNAd, RAd; \
173         roll $8, RNCd; \
174         roll $8, RNBd; \
175         roll $8, RAd; \
176         \
177         last_do16bit_shr(16, xor, RD, Essize, Es0, RND, Es0, RNC, RT0, RT1); \
178         last_do16bit(        xor, RD, Essize, Es0, RNB, Es0, RA,  RT0, RT1); \
179         movl (((next_r) * 16) + 3 * 4)(CTX), RDd; \
180         roll $8, RNCd; \
181         xorl RNDd, RDd; \
182         roll $8, RNBd; \
183         roll $8, RAd; \
184         roll $8, RDd; \
185         \
186         last_do16bit_shr(16, xor, RC, Essize, Es0, RNC, Es0, RNB, RT0, RT1); \
187         last_do16bit(        xor, RC, Essize, Es0, RA,  Es0, RD,  RT0, RT1); \
188         movl (((next_r) * 16) + 2 * 4)(CTX), RCd; \
189         roll $8, RNBd; \
190         xorl RNCd, RCd; \
191         roll $8, RAd; \
192         roll $8, RDd; \
193         roll $8, RCd; \
194         \
195         last_do16bit_shr(16, xor, RB, Essize, Es0, RNB, Es0, RA,  RT0, RT1); \
196         last_do16bit(        xor, RB, Essize, Es0, RD,  Es0, RC,  RT0, RT1); \
197         movl (((next_r) * 16) + 1 * 4)(CTX), RBd; \
198         roll $8, RAd; \
199         xorl RNBd, RBd; \
200         roll $16, RDd; \
201         roll $24, RCd;
202
203 #define firstencround(round) \
204         addroundkey(round, RA, RB, RC, RD); \
205         do_encround((round) + 1);
206
207 #define encround(round) \
208         do_encround((round) + 1);
209
210 #define lastencround(round) \
211         do_lastencround((round) + 1);
212
213 .align 8
214 .globl _gcry_aes_amd64_encrypt_block
215 ELF(.type   _gcry_aes_amd64_encrypt_block,@function;)
216
217 _gcry_aes_amd64_encrypt_block:
218         /* input:
219          *      %rdi: keysched, CTX
220          *      %rsi: dst
221          *      %rdx: src
222          *      %ecx: number of rounds.. 10, 12 or 14
223          *      %r8:  encryption tables
224          */
225         subq $(5 * 8), %rsp;
226         movq %rsi, (0 * 8)(%rsp);
227         movl %ecx, (1 * 8)(%rsp);
228         movq %rbp, (2 * 8)(%rsp);
229         movq %rbx, (3 * 8)(%rsp);
230         movq %r12, (4 * 8)(%rsp);
231
232         leaq (%r8), RTAB;
233
234         /* read input block */
235         movl 0 * 4(%rdx), RAd;
236         movl 1 * 4(%rdx), RBd;
237         movl 2 * 4(%rdx), RCd;
238         movl 3 * 4(%rdx), RDd;
239
240         firstencround(0);
241         encround(1);
242         encround(2);
243         encround(3);
244         encround(4);
245         encround(5);
246         encround(6);
247         encround(7);
248         encround(8);
249         cmpl $12, (1 * 8)(%rsp);
250         jnb .Lenc_not_128;
251         lastencround(9);
252
253 .align 4
254 .Lenc_done:
255         /* write output block */
256         movq (0 * 8)(%rsp), %rsi;
257         movl RAd, 0 * 4(%rsi);
258         movl RBd, 1 * 4(%rsi);
259         movl RCd, 2 * 4(%rsi);
260         movl RDd, 3 * 4(%rsi);
261
262         movq (4 * 8)(%rsp), %r12;
263         movq (3 * 8)(%rsp), %rbx;
264         movq (2 * 8)(%rsp), %rbp;
265         addq $(5 * 8), %rsp;
266
267         movl $(6 * 8), %eax;
268         ret;
269
270 .align 4
271 .Lenc_not_128:
272         je .Lenc_192
273
274         encround(9);
275         encround(10);
276         encround(11);
277         encround(12);
278         lastencround(13);
279
280         jmp .Lenc_done;
281
282 .align 4
283 .Lenc_192:
284         encround(9);
285         encround(10);
286         lastencround(11);
287
288         jmp .Lenc_done;
289 ELF(.size _gcry_aes_amd64_encrypt_block,.-_gcry_aes_amd64_encrypt_block;)
290
291 #define do_decround(next_r) \
292         do16bit_shr(16, mov, RA, Dsize, D0, RNA, D0, RNB, RT0, RT1); \
293         do16bit(        mov, RA, Dsize, D0, RNC, D0, RND, RT0, RT1); \
294         movl (((next_r) * 16) + 0 * 4)(CTX), RAd; \
295         roll $8, RNBd; \
296         xorl RNAd, RAd; \
297         roll $8, RNCd; \
298         roll $8, RNDd; \
299         roll $8, RAd; \
300         \
301         do16bit_shr(16, xor, RB, Dsize, D0, RNB, D0, RNC, RT0, RT1); \
302         do16bit(        xor, RB, Dsize, D0, RND, D0, RA,  RT0, RT1); \
303         movl (((next_r) * 16) + 1 * 4)(CTX), RBd; \
304         roll $8, RNCd; \
305         xorl RNBd, RBd; \
306         roll $8, RNDd; \
307         roll $8, RAd; \
308         roll $8, RBd; \
309         \
310         do16bit_shr(16, xor, RC, Dsize, D0, RNC, D0, RND, RT0, RT1); \
311         do16bit(        xor, RC, Dsize, D0, RA,  D0, RB,  RT0, RT1); \
312         movl (((next_r) * 16) + 2 * 4)(CTX), RCd; \
313         roll $8, RNDd; \
314         xorl RNCd, RCd; \
315         roll $8, RAd; \
316         roll $8, RBd; \
317         roll $8, RCd; \
318         \
319         do16bit_shr(16, xor, RD, Dsize, D0, RND, D0, RA,  RT0, RT1); \
320         do16bit(        xor, RD, Dsize, D0, RB,  D0, RC,  RT0, RT1); \
321         movl (((next_r) * 16) + 3 * 4)(CTX), RDd; \
322         roll $8, RAd; \
323         xorl RNDd, RDd; \
324         roll $16, RBd; \
325         roll $24, RCd;
326
327 #define do_lastdecround(next_r) \
328         do16bit_shr(16, movzb, RA, Dssize, Ds0, RNA, Ds0, RNB, RT0, RT1); \
329         do16bit(        movzb, RA, Dssize, Ds0, RNC, Ds0, RND, RT0, RT1); \
330         movl (((next_r) * 16) + 0 * 4)(CTX), RAd; \
331         roll $8, RNBd; \
332         xorl RNAd, RAd; \
333         roll $8, RNCd; \
334         roll $8, RNDd; \
335         roll $8, RAd; \
336         \
337         last_do16bit_shr(16, xor, RB, Dssize, Ds0, RNB, Ds0, RNC, RT0, RT1); \
338         last_do16bit(        xor, RB, Dssize, Ds0, RND, Ds0, RA,  RT0, RT1); \
339         movl (((next_r) * 16) + 1 * 4)(CTX), RBd; \
340         roll $8, RNCd; \
341         xorl RNBd, RBd; \
342         roll $8, RNDd; \
343         roll $8, RAd; \
344         roll $8, RBd; \
345         \
346         last_do16bit_shr(16, xor, RC, Dssize, Ds0, RNC, Ds0, RND, RT0, RT1); \
347         last_do16bit(        xor, RC, Dssize, Ds0, RA,  Ds0, RB,  RT0, RT1); \
348         movl (((next_r) * 16) + 2 * 4)(CTX), RCd; \
349         roll $8, RNDd; \
350         xorl RNCd, RCd; \
351         roll $8, RAd; \
352         roll $8, RBd; \
353         roll $8, RCd; \
354         \
355         last_do16bit_shr(16, xor, RD, Dssize, Ds0, RND, Ds0, RA,  RT0, RT1); \
356         last_do16bit(        xor, RD, Dssize, Ds0, RB,  Ds0, RC,  RT0, RT1); \
357         movl (((next_r) * 16) + 3 * 4)(CTX), RDd; \
358         roll $8, RAd; \
359         xorl RNDd, RDd; \
360         roll $16, RBd; \
361         roll $24, RCd;
362
363 #define firstdecround(round) \
364         addroundkey((round + 1), RA, RB, RC, RD); \
365         do_decround(round);
366
367 #define decround(round) \
368         do_decround(round);
369
370 #define lastdecround(round) \
371         do_lastdecround(round);
372
373 .align 8
374 .globl _gcry_aes_amd64_decrypt_block
375 ELF(.type   _gcry_aes_amd64_decrypt_block,@function;)
376
377 _gcry_aes_amd64_decrypt_block:
378         /* input:
379          *      %rdi: keysched, CTX
380          *      %rsi: dst
381          *      %rdx: src
382          *      %ecx: number of rounds.. 10, 12 or 14
383          *      %r8:  decryption tables
384          */
385         subq $(5 * 8), %rsp;
386         movq %rsi, (0 * 8)(%rsp);
387         movl %ecx, (1 * 8)(%rsp);
388         movq %rbp, (2 * 8)(%rsp);
389         movq %rbx, (3 * 8)(%rsp);
390         movq %r12, (4 * 8)(%rsp);
391
392         leaq (%r8), RTAB;
393
394         /* read input block */
395         movl 0 * 4(%rdx), RAd;
396         movl 1 * 4(%rdx), RBd;
397         movl 2 * 4(%rdx), RCd;
398         movl 3 * 4(%rdx), RDd;
399
400         cmpl $12, (1 * 8)(%rsp);
401         jnb .Ldec_256;
402
403         firstdecround(9);
404 .align 4
405 .Ldec_tail:
406         decround(8);
407         decround(7);
408         decround(6);
409         decround(5);
410         decround(4);
411         decround(3);
412         decround(2);
413         decround(1);
414         lastdecround(0);
415
416         /* write output block */
417         movq (0 * 8)(%rsp), %rsi;
418         movl RAd, 0 * 4(%rsi);
419         movl RBd, 1 * 4(%rsi);
420         movl RCd, 2 * 4(%rsi);
421         movl RDd, 3 * 4(%rsi);
422
423         movq (4 * 8)(%rsp), %r12;
424         movq (3 * 8)(%rsp), %rbx;
425         movq (2 * 8)(%rsp), %rbp;
426         addq $(5 * 8), %rsp;
427
428         movl $(6 * 8), %eax;
429         ret;
430
431 .align 4
432 .Ldec_256:
433         je .Ldec_192;
434
435         firstdecround(13);
436         decround(12);
437         decround(11);
438         decround(10);
439         decround(9);
440
441         jmp .Ldec_tail;
442
443 .align 4
444 .Ldec_192:
445         firstdecround(11);
446         decround(10);
447         decround(9);
448
449         jmp .Ldec_tail;
450 ELF(.size _gcry_aes_amd64_decrypt_block,.-_gcry_aes_amd64_decrypt_block;)
451
452 #endif /*USE_AES*/
453 #endif /*__x86_64*/