Add crypto hash SM3.
[libgcrypt.git] / cipher / whirlpool-sse2-amd64.S
1 /* whirlpool-sse2-amd64.S  -  AMD64 assembly implementation of Whirlpool
2  *
3  * Copyright (C) 2014 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_WHIRLPOOL)
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 /* look-up table offsets on RTAB */
41 #define RC (0)
42 #define C0 (RC + (8 * 10))
43 #define C1 (C0 + (8 * 256))
44 #define C2 (C1 + (8 * 256))
45 #define C3 (C2 + (8 * 256))
46 #define C4 (C3 + (8 * 256))
47 #define C5 (C4 + (8 * 256))
48 #define C6 (C5 + (8 * 256))
49 #define C7 (C6 + (8 * 256))
50
51 /* stack variables */
52 #define STACK_DATAP  (0)
53 #define STACK_STATEP (STACK_DATAP + 8)
54 #define STACK_ROUNDS (STACK_STATEP + 8)
55 #define STACK_NBLKS  (STACK_ROUNDS + 8)
56 #define STACK_RBP    (STACK_NBLKS + 8)
57 #define STACK_RBX    (STACK_RBP + 8)
58 #define STACK_R12    (STACK_RBX + 8)
59 #define STACK_R13    (STACK_R12 + 8)
60 #define STACK_R14    (STACK_R13 + 8)
61 #define STACK_R15    (STACK_R14 + 8)
62 #define STACK_MAX    (STACK_R15 + 8)
63
64 /* register macros */
65 #define RTAB    %rbp
66
67 #define RI1     %rax
68 #define RI2     %rbx
69 #define RI3     %rcx
70 #define RI4     %rdx
71
72 #define RI1d    %eax
73 #define RI2d    %ebx
74 #define RI3d    %ecx
75 #define RI4d    %edx
76
77 #define RI1bl   %al
78 #define RI2bl   %bl
79 #define RI3bl   %cl
80 #define RI4bl   %dl
81
82 #define RI1bh   %ah
83 #define RI2bh   %bh
84 #define RI3bh   %ch
85 #define RI4bh   %dh
86
87 #define RB0     %r8
88 #define RB1     %r9
89 #define RB2     %r10
90 #define RB3     %r11
91 #define RB4     %r12
92 #define RB5     %r13
93 #define RB6     %r14
94 #define RB7     %r15
95
96 #define RT0     %rsi
97 #define RT1     %rdi
98
99 #define RT0d    %esi
100 #define RT1d    %edi
101
102 #define XKEY0   %xmm0
103 #define XKEY1   %xmm1
104 #define XKEY2   %xmm2
105 #define XKEY3   %xmm3
106 #define XKEY4   %xmm4
107 #define XKEY5   %xmm5
108 #define XKEY6   %xmm6
109 #define XKEY7   %xmm7
110
111 #define XSTATE0 %xmm8
112 #define XSTATE1 %xmm9
113 #define XSTATE2 %xmm10
114 #define XSTATE3 %xmm11
115 #define XSTATE4 %xmm12
116 #define XSTATE5 %xmm13
117 #define XSTATE6 %xmm14
118 #define XSTATE7 %xmm15
119
120 /***********************************************************************
121  * AMD64 assembly implementation of Whirlpool.
122  *  - Using table-lookups
123  *  - Store state in XMM registers
124  ***********************************************************************/
125 #define __do_whirl(op, ri, \
126                    b0, b1, b2, b3, b4, b5, b6, b7, \
127                    load_ri, load_arg) \
128         movzbl          ri ## bl,       RT0d; \
129         movzbl          ri ## bh,       RT1d; \
130         shrq            $16,            ri; \
131         op ## q         C7(RTAB,RT0,8), b7; \
132         op ## q         C6(RTAB,RT1,8), b6; \
133         movzbl          ri ## bl,       RT0d; \
134         movzbl          ri ## bh,       RT1d; \
135         shrq            $16,            ri; \
136         op ## q         C5(RTAB,RT0,8), b5; \
137         op ## q         C4(RTAB,RT1,8), b4; \
138         movzbl          ri ## bl,       RT0d; \
139         movzbl          ri ## bh,       RT1d; \
140         shrl            $16,            ri ## d; \
141         op ## q         C3(RTAB,RT0,8), b3; \
142         op ## q         C2(RTAB,RT1,8), b2; \
143         movzbl          ri ## bl,       RT0d; \
144         movzbl          ri ## bh,       RT1d; \
145         load_ri(        load_arg,       ri); \
146         op ## q         C1(RTAB,RT0,8), b1; \
147         op ## q         C0(RTAB,RT1,8), b0;
148
149 #define do_whirl(op, ri, rb_add, load_ri, load_arg) \
150         __do_whirl(op, ##ri, rb_add, load_ri, load_arg)
151
152 #define dummy(...) /*_*/
153
154 #define do_movq(src, dst) movq src, dst;
155
156 #define RB_ADD0 RB0, RB1, RB2, RB3, RB4, RB5, RB6, RB7
157 #define RB_ADD1 RB1, RB2, RB3, RB4, RB5, RB6, RB7, RB0
158 #define RB_ADD2 RB2, RB3, RB4, RB5, RB6, RB7, RB0, RB1
159 #define RB_ADD3 RB3, RB4, RB5, RB6, RB7, RB0, RB1, RB2
160 #define RB_ADD4 RB4, RB5, RB6, RB7, RB0, RB1, RB2, RB3
161 #define RB_ADD5 RB5, RB6, RB7, RB0, RB1, RB2, RB3, RB4
162 #define RB_ADD6 RB6, RB7, RB0, RB1, RB2, RB3, RB4, RB5
163 #define RB_ADD7 RB7, RB0, RB1, RB2, RB3, RB4, RB5, RB6
164
165 .align 8
166 .globl _gcry_whirlpool_transform_amd64
167 ELF(.type  _gcry_whirlpool_transform_amd64,@function;)
168
169 _gcry_whirlpool_transform_amd64:
170         /* input:
171          *      %rdi: state
172          *      %rsi: inblk
173          *      %rdx: nblks
174          *      %rcx: look-up tables
175          */
176         cmp $0, %rdx;
177         je .Lskip;
178
179         subq $STACK_MAX, %rsp;
180         movq %rbp, STACK_RBP(%rsp);
181         movq %rbx, STACK_RBX(%rsp);
182         movq %r12, STACK_R12(%rsp);
183         movq %r13, STACK_R13(%rsp);
184         movq %r14, STACK_R14(%rsp);
185         movq %r15, STACK_R15(%rsp);
186
187         movq %rdx, STACK_NBLKS(%rsp);
188         movq %rdi, STACK_STATEP(%rsp);
189         movq %rsi, STACK_DATAP(%rsp);
190
191         movq %rcx, RTAB;
192
193         jmp .Lfirst_block;
194
195 .align 8
196 .Lblock_loop:
197         movq STACK_DATAP(%rsp), %rsi;
198         movq RI1, %rdi;
199
200 .Lfirst_block:
201         /* load data_block */
202         movq 0*8(%rsi), RB0;
203         movq 1*8(%rsi), RB1;
204         bswapq RB0;
205         movq 2*8(%rsi), RB2;
206         bswapq RB1;
207         movq 3*8(%rsi), RB3;
208         bswapq RB2;
209         movq 4*8(%rsi), RB4;
210         bswapq RB3;
211         movq 5*8(%rsi), RB5;
212         bswapq RB4;
213         movq RB0, XSTATE0;
214         movq 6*8(%rsi), RB6;
215         bswapq RB5;
216         movq RB1, XSTATE1;
217         movq 7*8(%rsi), RB7;
218         bswapq RB6;
219         movq RB2, XSTATE2;
220         bswapq RB7;
221         movq RB3, XSTATE3;
222         movq RB4, XSTATE4;
223         movq RB5, XSTATE5;
224         movq RB6, XSTATE6;
225         movq RB7, XSTATE7;
226
227         /* load key */
228         movq 0*8(%rdi), XKEY0;
229         movq 1*8(%rdi), XKEY1;
230         movq 2*8(%rdi), XKEY2;
231         movq 3*8(%rdi), XKEY3;
232         movq 4*8(%rdi), XKEY4;
233         movq 5*8(%rdi), XKEY5;
234         movq 6*8(%rdi), XKEY6;
235         movq 7*8(%rdi), XKEY7;
236
237         movq XKEY0, RI1;
238         movq XKEY1, RI2;
239         movq XKEY2, RI3;
240         movq XKEY3, RI4;
241
242         /* prepare and store state */
243         pxor XKEY0, XSTATE0;
244         pxor XKEY1, XSTATE1;
245         pxor XKEY2, XSTATE2;
246         pxor XKEY3, XSTATE3;
247         pxor XKEY4, XSTATE4;
248         pxor XKEY5, XSTATE5;
249         pxor XKEY6, XSTATE6;
250         pxor XKEY7, XSTATE7;
251
252         movq XSTATE0, 0*8(%rdi);
253         movq XSTATE1, 1*8(%rdi);
254         movq XSTATE2, 2*8(%rdi);
255         movq XSTATE3, 3*8(%rdi);
256         movq XSTATE4, 4*8(%rdi);
257         movq XSTATE5, 5*8(%rdi);
258         movq XSTATE6, 6*8(%rdi);
259         movq XSTATE7, 7*8(%rdi);
260
261         addq $64, STACK_DATAP(%rsp);
262         movl $(0), STACK_ROUNDS(%rsp);
263 .align 8
264 .Lround_loop:
265         do_whirl(mov, RI1 /*XKEY0*/, RB_ADD0, do_movq, XKEY4);
266         do_whirl(xor, RI2 /*XKEY1*/, RB_ADD1, do_movq, XKEY5);
267         do_whirl(xor, RI3 /*XKEY2*/, RB_ADD2, do_movq, XKEY6);
268         do_whirl(xor, RI4 /*XKEY3*/, RB_ADD3, do_movq, XKEY7);
269         do_whirl(xor, RI1 /*XKEY0*/, RB_ADD4, do_movq, XSTATE0);
270         do_whirl(xor, RI2 /*XKEY1*/, RB_ADD5, do_movq, XSTATE1);
271         do_whirl(xor, RI3 /*XKEY2*/, RB_ADD6, do_movq, XSTATE2);
272         do_whirl(xor, RI4 /*XKEY3*/, RB_ADD7, do_movq, XSTATE3);
273
274         movl STACK_ROUNDS(%rsp), RT0d;
275         movq RB1, XKEY1;
276         addl $1, STACK_ROUNDS(%rsp);
277         movq RB2, XKEY2;
278         movq RB3, XKEY3;
279         xorq RC(RTAB,RT0,8), RB0; /* Add round constant */
280         movq RB4, XKEY4;
281         movq RB5, XKEY5;
282         movq RB0, XKEY0;
283         movq RB6, XKEY6;
284         movq RB7, XKEY7;
285
286         do_whirl(xor, RI1 /*XSTATE0*/, RB_ADD0, do_movq, XSTATE4);
287         do_whirl(xor, RI2 /*XSTATE1*/, RB_ADD1, do_movq, XSTATE5);
288         do_whirl(xor, RI3 /*XSTATE2*/, RB_ADD2, do_movq, XSTATE6);
289         do_whirl(xor, RI4 /*XSTATE3*/, RB_ADD3, do_movq, XSTATE7);
290
291         cmpl $10, STACK_ROUNDS(%rsp);
292         je .Lis_last_round;
293
294         do_whirl(xor, RI1 /*XSTATE4*/, RB_ADD4, do_movq, XKEY0);
295         do_whirl(xor, RI2 /*XSTATE5*/, RB_ADD5, do_movq, XKEY1);
296         do_whirl(xor, RI3 /*XSTATE6*/, RB_ADD6, do_movq, XKEY2);
297         do_whirl(xor, RI4 /*XSTATE7*/, RB_ADD7, do_movq, XKEY3);
298         movq RB0, XSTATE0;
299         movq RB1, XSTATE1;
300         movq RB2, XSTATE2;
301         movq RB3, XSTATE3;
302         movq RB4, XSTATE4;
303         movq RB5, XSTATE5;
304         movq RB6, XSTATE6;
305         movq RB7, XSTATE7;
306
307         jmp .Lround_loop;
308 .align 8
309 .Lis_last_round:
310         do_whirl(xor, RI1 /*XSTATE4*/, RB_ADD4, dummy, _);
311         movq STACK_STATEP(%rsp), RI1;
312         do_whirl(xor, RI2 /*XSTATE5*/, RB_ADD5, dummy, _);
313         do_whirl(xor, RI3 /*XSTATE6*/, RB_ADD6, dummy, _);
314         do_whirl(xor, RI4 /*XSTATE7*/, RB_ADD7, dummy, _);
315
316         /* store state */
317         xorq RB0, 0*8(RI1);
318         xorq RB1, 1*8(RI1);
319         xorq RB2, 2*8(RI1);
320         xorq RB3, 3*8(RI1);
321         xorq RB4, 4*8(RI1);
322         xorq RB5, 5*8(RI1);
323         xorq RB6, 6*8(RI1);
324         xorq RB7, 7*8(RI1);
325
326         subq $1, STACK_NBLKS(%rsp);
327         jnz .Lblock_loop;
328
329         movq STACK_RBP(%rsp), %rbp;
330         movq STACK_RBX(%rsp), %rbx;
331         movq STACK_R12(%rsp), %r12;
332         movq STACK_R13(%rsp), %r13;
333         movq STACK_R14(%rsp), %r14;
334         movq STACK_R15(%rsp), %r15;
335         addq $STACK_MAX, %rsp;
336 .Lskip:
337         movl $(STACK_MAX + 8), %eax;
338         ret;
339 ELF(.size _gcry_whirlpool_transform_amd64,.-_gcry_whirlpool_transform_amd64;)
340
341 #endif
342 #endif