9de31686d062abf40671ba5f53d6d9c84849d21b
[openssl.git] / crypto / sha / asm / keccak1600-x86_64.pl
1 #!/usr/bin/env perl
2 # Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the OpenSSL license (the "License").  You may not use
5 # this file except in compliance with the License.  You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
8 #
9 # ====================================================================
10 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
11 # project. The module is, however, dual licensed under OpenSSL and
12 # CRYPTOGAMS licenses depending on where you obtain it. For further
13 # details see http://www.openssl.org/~appro/cryptogams/.
14 # ====================================================================
15 #
16 # Keccak-1600 for x86_86.
17 #
18 # June 2017.
19 #
20 # Below code is [lane complementing] KECCAK_2X implementation (see
21 # sha/keccak1600.c) with C[5] and D[5] held in register bank. Though
22 # instead of actually unrolling the loop pair-wise I simply flip
23 # pointers to T[][] and A[][] at the end of round. Since number of
24 # rounds is even, last round writes to A[][] and everything works out.
25
26 my @A = map([ 8*$_-100, 8*($_+1)-100, 8*($_+2)-100,
27               8*($_+3)-100, 8*($_+4)-100 ], (0,5,10,15,20));
28
29 my @C = ("%rax","%rbx","%rcx","%rdx","%rbp");
30 my @D = map("%r$_",(8..12));
31 my @T = map("%r$_",(13..14));
32 my $iotas = "%r15";
33
34 my @rhotates = ([  0,  1, 62, 28, 27 ],
35                 [ 36, 44,  6, 55, 20 ],
36                 [  3, 10, 43, 25, 39 ],
37                 [ 41, 45, 15, 21,  8 ],
38                 [ 18,  2, 61, 56, 14 ]);
39
40 $code.=<<___;
41 .text
42
43 .type   __KeccakF1600,\@function
44 .align  32
45 __KeccakF1600:
46         mov     $A[4][0](%rdi),@C[0]
47         mov     $A[4][1](%rdi),@C[1]
48         mov     $A[4][2](%rdi),@C[2]
49         mov     $A[4][3](%rdi),@C[3]
50         mov     $A[4][4](%rdi),@C[4]
51         jmp     .Loop
52
53 .align  32
54 .Loop:
55         xor     $A[0][0](%rdi),@C[0]
56         xor     $A[0][1](%rdi),@C[1]
57         xor     $A[0][2](%rdi),@C[2]
58         xor     $A[0][3](%rdi),@C[3]
59         xor     $A[0][4](%rdi),@C[4]
60
61         xor     $A[1][0](%rdi),@C[0]
62         xor     $A[1][1](%rdi),@C[1]
63         xor     $A[1][2](%rdi),@C[2]
64         xor     $A[1][3](%rdi),@C[3]
65         xor     $A[1][4](%rdi),@C[4]
66
67         xor     $A[2][0](%rdi),@C[0]
68         xor     $A[2][1](%rdi),@C[1]
69         xor     $A[2][2](%rdi),@C[2]
70         xor     $A[2][3](%rdi),@C[3]
71         xor     $A[2][4](%rdi),@C[4]
72
73         xor     $A[3][0](%rdi),@C[0]
74         xor     $A[3][1](%rdi),@C[1]
75         xor     $A[3][2](%rdi),@C[2]
76         xor     $A[3][3](%rdi),@C[3]
77         xor     $A[3][4](%rdi),@C[4]
78
79         mov     @C[2],@T[0]
80         rol     \$1,@C[2]
81         xor     @C[0],@C[2]             # D[1] = ROL64(C[2], 1) ^ C[0]
82
83         rol     \$1,@C[0]
84         xor     @C[3],@C[0]             # D[4] = ROL64(C[0], 1) ^ C[3]
85
86         rol     \$1,@C[3]
87         xor     @C[1],@C[3]             # D[2] = ROL64(C[3], 1) ^ C[1]
88
89         rol     \$1,@C[1]
90         xor     @C[4],@C[1]             # D[0] = ROL64(C[1], 1) ^ C[4]
91
92         rol     \$1,@C[4]
93         xor     @T[0],@C[4]             # D[3] = ROL64(C[4], 1) ^ C[2]
94 ___
95         my @E = @D;
96         @D = (@C[1],@C[2],@C[3],@C[4],@C[0]);
97         @C = @E;
98 $code.=<<___;
99         mov     $A[0][0](%rdi),@C[0]
100         mov     $A[1][1](%rdi),@C[1]
101         mov     $A[2][2](%rdi),@C[2]
102         mov     $A[3][3](%rdi),@C[3]
103         mov     $A[4][4](%rdi),@C[4]
104
105         xor     @D[0],@C[0]
106         xor     @D[1],@C[1]
107         xor     @D[2],@C[2]
108         xor     @D[3],@C[3]
109         xor     @D[4],@C[4]
110
111         rol     \$$rhotates[1][1],@C[1]
112         rol     \$$rhotates[2][2],@C[2]
113         rol     \$$rhotates[3][3],@C[3]
114         rol     \$$rhotates[4][4],@C[4]
115
116         mov     @C[1],@T[0]
117         or      @C[2],@C[1]
118         xor     @C[0],@C[1]             #           C[0] ^ ( C[1] | C[2])
119         xor     ($iotas),@C[1]
120         lea     8($iotas),$iotas
121         mov     @C[1],$A[0][0](%rsi)    # R[0][0] = C[0] ^ ( C[1] | C[2]) ^ iotas[i]
122
123         mov     @C[4],@T[1]
124         and     @C[3],@C[4]
125         xor     @C[2],@C[4]             #           C[2] ^ ( C[4] & C[3])
126         mov     @C[4],$A[0][2](%rsi)    # R[0][2] = C[2] ^ ( C[4] & C[3])
127
128         not     @C[2]
129         or      @C[3],@C[2]
130         xor     @T[0],@C[2]             #           C[1] ^ (~C[2] | C[3])
131         mov     @C[2],$A[0][1](%rsi)    # R[0][1] = C[1] ^ (~C[2] | C[3])
132
133         and     @C[0],@T[0]
134         xor     @T[1],@T[0]             #           C[4] ^ ( C[1] & C[0])
135         mov     @T[0],$A[0][4](%rsi)    # R[0][4] = C[4] ^ ( C[1] & C[0])
136
137         or      @C[0],@T[1]
138         xor     @C[3],@T[1]             #           C[3] ^ ( C[4] | C[0])
139         mov     @T[1],$A[0][3](%rsi)    # R[0][3] = C[3] ^ ( C[4] | C[0])
140
141
142         mov     $A[0][3](%rdi),@C[0]
143         mov     $A[1][4](%rdi),@C[1]
144         mov     $A[2][0](%rdi),@C[2]
145         mov     $A[3][1](%rdi),@C[3]
146         mov     $A[4][2](%rdi),@C[4]
147
148         xor     @D[3],@C[0]
149         xor     @D[4],@C[1]
150         xor     @D[0],@C[2]
151         xor     @D[1],@C[3]
152         xor     @D[2],@C[4]
153
154         rol     \$$rhotates[0][3],@C[0]
155         rol     \$$rhotates[1][4],@C[1]
156         rol     \$$rhotates[2][0],@C[2]
157         rol     \$$rhotates[3][1],@C[3]
158         rol     \$$rhotates[4][2],@C[4]
159
160         mov     @C[0],@T[0]
161         or      @C[4],@C[0]
162         xor     @C[3],@C[0]             #           C[3] ^ (C[0] |  C[4])
163         mov     @C[0],$A[1][3](%rsi)    # R[1][3] = C[3] ^ (C[0] |  C[4])
164
165         mov     @C[1],@T[1]
166         and     @T[0],@C[1]
167         xor     @C[4],@C[1]             #           C[4] ^ (C[1] &  C[0])
168         mov     @C[1],$A[1][4](%rsi)    # R[1][4] = C[4] ^ (C[1] &  C[0])
169
170         not     @C[4]
171         or      @C[3],@C[4]
172         xor     @C[2],@C[4]             #           C[2] ^ (~C[4] | C[3])
173         mov     @C[4],$A[1][2](%rsi)    # R[1][2] = C[2] ^ (~C[4] | C[3])
174
175         and     @C[2],@C[3]
176         xor     @T[1],@C[3]             #           C[1] ^ (C[3] &  C[2])
177         mov     @C[3],$A[1][1](%rsi)    # R[1][1] = C[1] ^ (C[3] &  C[2])
178
179         or      @C[2],@T[1]
180         xor     @T[0],@T[1]             #           C[0] ^ (C[1] |  C[2])
181         mov     @T[1],$A[1][0](%rsi)    # R[1][0] = C[0] ^ (C[1] |  C[2])
182
183
184         mov     $A[0][1](%rdi),@C[0]
185         mov     $A[1][2](%rdi),@C[1]
186         mov     $A[2][3](%rdi),@C[2]
187         mov     $A[3][4](%rdi),@C[3]
188         mov     $A[4][0](%rdi),@C[4]
189
190         xor     @D[1],@C[0]
191         xor     @D[2],@C[1]
192         xor     @D[3],@C[2]
193         xor     @D[4],@C[3]
194         xor     @D[0],@C[4]
195
196         rol     \$$rhotates[0][1],@C[0]
197         rol     \$$rhotates[1][2],@C[1]
198         rol     \$$rhotates[2][3],@C[2]
199         rol     \$$rhotates[3][4],@C[3]
200         rol     \$$rhotates[4][0],@C[4]
201
202         mov     @C[2],@T[0]
203         and     @C[3],@C[2]
204         xor     @C[1],@C[2]             #            C[1] ^ ( C[2] & C[3])
205         mov     @C[2],$A[2][1](%rsi)    # R[2][1] =  C[1] ^ ( C[2] & C[3])
206
207         mov     @C[4],@T[1]
208         not     @C[3]
209         and     @C[3],@C[4]
210         xor     @T[0],@C[4]             #            C[2] ^ ( C[4] & ~C[3])
211         mov     @C[4],$A[2][2](%rsi)    # R[2][2] =  C[2] ^ ( C[4] & ~C[3])
212
213         or      @C[1],@T[0]
214         xor     @C[0],@T[0]             #            C[0] ^ ( C[2] | C[1])
215         mov     @T[0],$A[2][0](%rsi)    # R[2][0] =  C[0] ^ ( C[2] | C[1])
216
217         and     @C[0],@C[1]
218         xor     @T[1],@C[1]             #            C[4] ^ ( C[1] & C[0])
219         mov     @C[1],$A[2][4](%rsi)    # R[2][4] =  C[4] ^ ( C[1] & C[0])
220
221         or      @T[1],@C[0]
222         xor     @C[3],@C[0]             #           ~C[3] ^ ( C[0] | C[4])
223         mov     @C[0],$A[2][3](%rsi)    # R[2][3] = ~C[3] ^ ( C[0] | C[4])
224
225
226         mov     $A[0][4](%rdi),@C[0]
227         mov     $A[1][0](%rdi),@C[1]
228         mov     $A[2][1](%rdi),@C[2]
229         mov     $A[3][2](%rdi),@C[3]
230         mov     $A[4][3](%rdi),@C[4]
231
232         xor     @D[4],@C[0]
233         xor     @D[0],@C[1]
234         xor     @D[1],@C[2]
235         xor     @D[2],@C[3]
236         xor     @D[3],@C[4]
237
238         rol     \$$rhotates[0][4],@C[0]
239         rol     \$$rhotates[1][0],@C[1]
240         rol     \$$rhotates[2][1],@C[2]
241         rol     \$$rhotates[3][2],@C[3]
242         rol     \$$rhotates[4][3],@C[4]
243
244         mov     @C[2],@T[0]
245         or      @C[3],@C[2]
246         xor     @C[1],@C[2]             #            C[1] ^ ( C[2] | C[3])
247         mov     @C[2],$A[3][1](%rsi)    # R[3][1] =  C[1] ^ ( C[2] | C[3])
248
249         mov     @C[4],@T[1]
250         not     @C[3]
251         or      @C[3],@C[4]
252         xor     @T[0],@C[4]             #            C[2] ^ ( C[4] | ~C[3])
253         mov     @C[4],$A[3][2](%rsi)    # R[3][2] =  C[2] ^ ( C[4] | ~C[3])
254
255         and     @C[1],@T[0]
256         xor     @C[0],@T[0]             #            C[0] ^ ( C[2] & C[1])
257         mov     @T[0],$A[3][0](%rsi)    # R[3][0] =  C[0] ^ ( C[2] & C[1])
258
259         or      @C[0],@C[1]
260         xor     @T[1],@C[1]             #            C[4] ^ ( C[1] | C[0])
261         mov     @C[1],$A[3][4](%rsi)    # R[3][4] =  C[4] ^ ( C[1] | C[0])
262
263         and     @T[1],@C[0]
264         xor     @C[3],@C[0]             #           ~C[3] ^ ( C[0] & C[4])
265         mov     @C[0],$A[3][3](%rsi)    # R[3][3] = ~C[3] ^ ( C[0] & C[4])
266
267
268         mov     $A[0][2](%rdi),@C[0]
269         mov     $A[1][3](%rdi),@C[1]
270         mov     $A[2][4](%rdi),@C[2]
271         mov     $A[3][0](%rdi),@C[3]
272         mov     $A[4][1](%rdi),@C[4]
273         xchg    %rsi,%rdi
274
275         xor     @D[2],@C[0]
276         xor     @D[3],@C[1]
277         xor     @D[4],@C[2]
278         xor     @D[0],@C[3]
279         xor     @D[1],@C[4]
280
281         rol     \$$rhotates[0][2],@C[0]
282         rol     \$$rhotates[1][3],@C[1]
283         rol     \$$rhotates[2][4],@C[2]
284         rol     \$$rhotates[3][0],@C[3]
285         rol     \$$rhotates[4][1],@C[4]
286
287         mov     @C[0],@T[0]
288         and     @C[1],@C[0]
289         xor     @C[4],@C[0]             #            C[4] ^ ( C[0] & C[1])
290         mov     @C[0],$A[4][4](%rdi)    # R[4][4] =  C[4] ^ ( C[0] & C[1])
291
292         mov     @C[2],@T[1]
293         not     @C[1]
294         and     @C[1],@C[2]
295         xor     @T[0],@C[2]             #            C[0] ^ ( C[2] & ~C[1])
296         mov     @C[2],$A[4][0](%rdi)    # R[4][0] =  C[0] ^ ( C[2] & ~C[1])
297
298         or      @C[4],@T[0]
299         xor     @C[3],@T[0]             #            C[3] ^ ( C[0] | C[4])
300         mov     @T[0],$A[4][3](%rdi)    # R[4][3] =  C[3] ^ ( C[0] | C[4])
301
302         and     @C[3],@C[4]
303         xor     @T[1],@C[4]             #            C[2] ^ ( C[4] & C[3])
304         mov     @C[4],$A[4][2](%rdi)    # R[4][2] =  C[2] ^ ( C[4] & C[3])
305
306         or      @T[1],@C[3]
307         xor     @C[1],@C[3]             #           ~C[1] ^ ( C[2] | C[3])
308         mov     @C[3],$A[4][1](%rdi)    # R[4][1] = ~C[1] ^ ( C[2] | C[3])
309
310         mov     @C[2],@D[4]             # harmonize with the loop top
311         mov     @C[3],@D[0]
312         mov     @C[4],@D[1]
313         mov     @T[0],@D[2]
314         mov     @C[0],@D[3]
315
316         test    \$255,$iotas
317         jnz     .Loop
318
319         lea     -192($iotas),$iotas     # rewind iotas
320         ret
321 .size   __KeccakF1600,.-__KeccakF1600
322
323 .globl  KeccakF1600
324 .type   KeccakF1600,\@function
325 .align  32
326 KeccakF1600:
327         push    %rbx
328         push    %rbp
329         push    %r12
330         push    %r13
331         push    %r14
332         push    %r15
333
334         lea     100(%rdi),%rdi          # size optimization
335         sub     \$200,%rsp
336
337         notq    $A[0][1](%rdi)
338         notq    $A[0][2](%rdi)
339         notq    $A[1][3](%rdi)
340         notq    $A[2][2](%rdi)
341         notq    $A[3][2](%rdi)
342         notq    $A[4][0](%rdi)
343
344         lea     iotas(%rip),$iotas
345         lea     100(%rsp),%rsi          # size optimization
346
347         call    __KeccakF1600
348
349         notq    $A[0][1](%rdi)
350         notq    $A[0][2](%rdi)
351         notq    $A[1][3](%rdi)
352         notq    $A[2][2](%rdi)
353         notq    $A[3][2](%rdi)
354         notq    $A[4][0](%rdi)
355         lea     -100(%rdi),%rdi         # preserve A[][]
356
357         add     \$200,%rsp
358
359         pop     %r15
360         pop     %r14
361         pop     %r13
362         pop     %r12
363         pop     %rbp
364         pop     %rbx
365         ret
366 .size   KeccakF1600,.-KeccakF1600
367 ___
368
369 { my ($A_flat,$inp,$len,$bsz) = ("%rdi","%rsi","%rdx","%rcx");
370      ($A_flat,$inp) = ("%r8","%r9");
371 $code.=<<___;
372 .globl  SHA3_absorb
373 .type   SHA3_absorb,\@function
374 .align  32
375 SHA3_absorb:
376         push    %rbx
377         push    %rbp
378         push    %r12
379         push    %r13
380         push    %r14
381         push    %r15
382
383         lea     100(%rdi),%rdi          # size optimization
384         sub     \$232,%rsp
385
386         mov     %rsi,$inp
387         lea     100(%rsp),%rsi          # size optimization
388
389         notq    $A[0][1](%rdi)
390         notq    $A[0][2](%rdi)
391         notq    $A[1][3](%rdi)
392         notq    $A[2][2](%rdi)
393         notq    $A[3][2](%rdi)
394         notq    $A[4][0](%rdi)
395         lea     iotas(%rip),$iotas
396
397         mov     $bsz,216-100(%rsi)      # save bsz
398
399 .Loop_absorb:
400         cmp     $bsz,$len
401         jc      .Ldone_absorb
402
403         shr     \$3,$bsz
404         lea     -100(%rdi),$A_flat
405
406 .Lblock_absorb:
407         mov     ($inp),%rax
408         lea     8($inp),$inp
409         xor     ($A_flat),%rax
410         lea     8($A_flat),$A_flat
411         sub     \$8,$len
412         mov     %rax,-8($A_flat)
413         dec     $bsz
414         jnz     .Lblock_absorb
415
416         mov     $inp,200-100(%rsi)      # save inp
417         mov     $len,208-100(%rsi)      # save len
418         call    __KeccakF1600
419         mov     200-100(%rsi),$inp      # pull inp
420         mov     208-100(%rsi),$len      # pull len
421         mov     216-100(%rsi),$bsz      # pull bsz
422         jmp     .Loop_absorb
423
424 .align  32
425 .Ldone_absorb:
426         mov     $len,%rax               # return value
427
428         notq    $A[0][1](%rdi)
429         notq    $A[0][2](%rdi)
430         notq    $A[1][3](%rdi)
431         notq    $A[2][2](%rdi)
432         notq    $A[3][2](%rdi)
433         notq    $A[4][0](%rdi)
434
435         add     \$232,%rsp
436
437         pop     %r15
438         pop     %r14
439         pop     %r13
440         pop     %r12
441         pop     %rbp
442         pop     %rbx
443         ret
444 .size   SHA3_absorb,.-SHA3_absorb
445 ___
446 }
447 { my ($A_flat,$out,$len,$bsz) = ("%rdi","%rsi","%rdx","%rcx");
448      ($out,$len,$bsz) = ("%r12","%r13","%r14");
449
450 $code.=<<___;
451 .globl  SHA3_squeeze
452 .type   SHA3_squeeze,\@function
453 .align  32
454 SHA3_squeeze:
455         push    %r12
456         push    %r13
457         push    %r14
458
459         shr     \$3,%rcx
460         mov     $A_flat,%r8
461         mov     %rsi,$out
462         mov     %rdx,$len
463         mov     %rcx,$bsz
464         jmp     .Loop_squeeze
465
466 .align  32
467 .Loop_squeeze:
468         cmp     \$8,$len
469         jb      .Ltail_squeeze
470
471         mov     (%r8),%rax
472         lea     8(%r8),%r8
473         mov     %rax,($out)
474         lea     8($out),$out
475         sub     \$8,$len                # len -= 8
476         jz      .Ldone_squeeze
477
478         dec     %rcx                    # bsz--
479         jnz     .Loop_squeeze
480
481         call    KeccakF1600
482         mov     $A_flat,%r8
483         mov     $bsz,%rcx
484         jmp     .Loop_squeeze
485
486 .Ltail_squeeze:
487         mov     %r8, %rsi
488         mov     $out,%rdi
489         mov     $len,%rcx
490         .byte   0xf3,0xa4               # rep   movsb
491
492 .Ldone_squeeze:
493         pop     %r14
494         pop     %r13
495         pop     %r12
496         ret
497 .size   SHA3_squeeze,.-SHA3_squeeze
498 ___
499 }
500 $code.=<<___;
501 .align  256
502         .quad   0,0,0,0,0,0,0,0
503 .type   iotas,\@object
504 iotas:
505         .quad   0x0000000000000001
506         .quad   0x0000000000008082
507         .quad   0x800000000000808a
508         .quad   0x8000000080008000
509         .quad   0x000000000000808b
510         .quad   0x0000000080000001
511         .quad   0x8000000080008081
512         .quad   0x8000000000008009
513         .quad   0x000000000000008a
514         .quad   0x0000000000000088
515         .quad   0x0000000080008009
516         .quad   0x000000008000000a
517         .quad   0x000000008000808b
518         .quad   0x800000000000008b
519         .quad   0x8000000000008089
520         .quad   0x8000000000008003
521         .quad   0x8000000000008002
522         .quad   0x8000000000000080
523         .quad   0x000000000000800a
524         .quad   0x800000008000000a
525         .quad   0x8000000080008081
526         .quad   0x8000000000008080
527         .quad   0x0000000080000001
528         .quad   0x8000000080008008
529 .size   iotas,.-iotas
530 .asciz  "Keccak-1600 absorb and squeeze for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
531 ___
532
533 print $code;
534
535 close STDOUT;