09160544a020856867f8bde50e5c45750501c3a0
[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 ########################################################################
27 # Numbers are cycles per processed byte out of large message.
28 #
29 #                       r=1088
30 #
31 # P4                    45.8
32 # Core 2                14.2
33 # Sandy Bridge          13.0
34 # Haswell               9.8
35 # Skylake               9.4
36 # Silvermont            22.4
37 # Goldmont              18.0
38 # VIA Nano              19.1
39 # Sledgehammer          13.8
40 # Bulldozer             16.7
41
42 $flavour = shift;
43 $output  = shift;
44 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
45
46 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
47
48 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
49 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
50 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
51 die "can't locate x86_64-xlate.pl";
52
53 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
54 *STDOUT=*OUT;
55
56 my @A = map([ 8*$_-100, 8*($_+1)-100, 8*($_+2)-100,
57               8*($_+3)-100, 8*($_+4)-100 ], (0,5,10,15,20));
58
59 my @C = ("%rax","%rbx","%rcx","%rdx","%rbp");
60 my @D = map("%r$_",(8..12));
61 my @T = map("%r$_",(13..14));
62 my $iotas = "%r15";
63
64 my @rhotates = ([  0,  1, 62, 28, 27 ],
65                 [ 36, 44,  6, 55, 20 ],
66                 [  3, 10, 43, 25, 39 ],
67                 [ 41, 45, 15, 21,  8 ],
68                 [ 18,  2, 61, 56, 14 ]);
69
70 $code.=<<___;
71 .text
72
73 .type   __KeccakF1600,\@function
74 .align  32
75 __KeccakF1600:
76         mov     $A[4][0](%rdi),@C[0]
77         mov     $A[4][1](%rdi),@C[1]
78         mov     $A[4][2](%rdi),@C[2]
79         mov     $A[4][3](%rdi),@C[3]
80         mov     $A[4][4](%rdi),@C[4]
81         jmp     .Loop
82
83 .align  32
84 .Loop:
85         xor     $A[0][0](%rdi),@C[0]
86         xor     $A[0][1](%rdi),@C[1]
87         xor     $A[0][2](%rdi),@C[2]
88         xor     $A[0][3](%rdi),@C[3]
89         xor     $A[0][4](%rdi),@C[4]
90
91         xor     $A[1][0](%rdi),@C[0]
92         xor     $A[1][1](%rdi),@C[1]
93         xor     $A[1][2](%rdi),@C[2]
94         xor     $A[1][3](%rdi),@C[3]
95         xor     $A[1][4](%rdi),@C[4]
96
97         xor     $A[2][0](%rdi),@C[0]
98         xor     $A[2][1](%rdi),@C[1]
99         xor     $A[2][2](%rdi),@C[2]
100         xor     $A[2][3](%rdi),@C[3]
101         xor     $A[2][4](%rdi),@C[4]
102
103         xor     $A[3][0](%rdi),@C[0]
104         xor     $A[3][1](%rdi),@C[1]
105         xor     $A[3][2](%rdi),@C[2]
106         xor     $A[3][3](%rdi),@C[3]
107         xor     $A[3][4](%rdi),@C[4]
108
109         mov     @C[2],@T[0]
110         rol     \$1,@C[2]
111         mov     $A[0][0](%rdi),@D[0]
112         xor     @C[0],@C[2]             # D[1] = ROL64(C[2], 1) ^ C[0]
113
114         rol     \$1,@C[0]
115         mov     $A[1][1](%rdi),@D[1]
116         xor     @C[3],@C[0]             # D[4] = ROL64(C[0], 1) ^ C[3]
117
118         rol     \$1,@C[3]
119         mov     $A[2][2](%rdi),@D[2]
120         xor     @C[1],@C[3]             # D[2] = ROL64(C[3], 1) ^ C[1]
121
122         rol     \$1,@C[1]
123         mov     $A[3][3](%rdi),@D[3]
124         xor     @C[4],@C[1]             # D[0] = ROL64(C[1], 1) ^ C[4]
125
126         rol     \$1,@C[4]
127         mov     $A[4][4](%rdi),@D[4]
128         xor     @T[0],@C[4]             # D[3] = ROL64(C[4], 1) ^ C[2]
129 ___
130         my @E = @D;
131         @D = (@C[1],@C[2],@C[3],@C[4],@C[0]);
132         @C = @E;
133 $code.=<<___;
134         xor     @D[0],@C[0]
135         xor     @D[1],@C[1]
136         xor     @D[2],@C[2]
137         xor     @D[3],@C[3]
138         xor     @D[4],@C[4]
139
140         rol     \$$rhotates[1][1],@C[1]
141         rol     \$$rhotates[2][2],@C[2]
142         rol     \$$rhotates[3][3],@C[3]
143         rol     \$$rhotates[4][4],@C[4]
144
145         mov     @C[1],@T[0]
146         or      @C[2],@C[1]
147         xor     @C[0],@C[1]             #           C[0] ^ ( C[1] | C[2])
148         xor     ($iotas),@C[1]
149         lea     8($iotas),$iotas
150         mov     @C[1],$A[0][0](%rsi)    # R[0][0] = C[0] ^ ( C[1] | C[2]) ^ iotas[i]
151
152         mov     @C[4],@T[1]
153         and     @C[3],@C[4]
154         xor     @C[2],@C[4]             #           C[2] ^ ( C[4] & C[3])
155         mov     @C[4],$A[0][2](%rsi)    # R[0][2] = C[2] ^ ( C[4] & C[3])
156
157         not     @C[2]
158         or      @C[3],@C[2]
159         xor     @T[0],@C[2]             #           C[1] ^ (~C[2] | C[3])
160         mov     @C[2],$A[0][1](%rsi)    # R[0][1] = C[1] ^ (~C[2] | C[3])
161
162         and     @C[0],@T[0]
163         xor     @T[1],@T[0]             #           C[4] ^ ( C[1] & C[0])
164         mov     @T[0],$A[0][4](%rsi)    # R[0][4] = C[4] ^ ( C[1] & C[0])
165
166         or      @C[0],@T[1]
167         xor     @C[3],@T[1]             #           C[3] ^ ( C[4] | C[0])
168         mov     @T[1],$A[0][3](%rsi)    # R[0][3] = C[3] ^ ( C[4] | C[0])
169
170
171         mov     $A[0][3](%rdi),@C[0]
172         mov     $A[1][4](%rdi),@C[1]
173         mov     $A[2][0](%rdi),@C[2]
174         mov     $A[3][1](%rdi),@C[3]
175         mov     $A[4][2](%rdi),@C[4]
176
177         xor     @D[3],@C[0]
178         xor     @D[4],@C[1]
179         xor     @D[0],@C[2]
180         xor     @D[1],@C[3]
181         xor     @D[2],@C[4]
182
183         rol     \$$rhotates[0][3],@C[0]
184         rol     \$$rhotates[1][4],@C[1]
185         rol     \$$rhotates[2][0],@C[2]
186         rol     \$$rhotates[3][1],@C[3]
187         rol     \$$rhotates[4][2],@C[4]
188
189         mov     @C[0],@T[0]
190         or      @C[4],@C[0]
191         xor     @C[3],@C[0]             #           C[3] ^ (C[0] |  C[4])
192         mov     @C[0],$A[1][3](%rsi)    # R[1][3] = C[3] ^ (C[0] |  C[4])
193
194         mov     @C[1],@T[1]
195         and     @T[0],@C[1]
196         xor     @C[4],@C[1]             #           C[4] ^ (C[1] &  C[0])
197         mov     @C[1],$A[1][4](%rsi)    # R[1][4] = C[4] ^ (C[1] &  C[0])
198
199         not     @C[4]
200         or      @C[3],@C[4]
201         xor     @C[2],@C[4]             #           C[2] ^ (~C[4] | C[3])
202         mov     @C[4],$A[1][2](%rsi)    # R[1][2] = C[2] ^ (~C[4] | C[3])
203
204         and     @C[2],@C[3]
205         xor     @T[1],@C[3]             #           C[1] ^ (C[3] &  C[2])
206         mov     @C[3],$A[1][1](%rsi)    # R[1][1] = C[1] ^ (C[3] &  C[2])
207
208         or      @C[2],@T[1]
209         xor     @T[0],@T[1]             #           C[0] ^ (C[1] |  C[2])
210         mov     @T[1],$A[1][0](%rsi)    # R[1][0] = C[0] ^ (C[1] |  C[2])
211
212
213         mov     $A[0][1](%rdi),@C[0]
214         mov     $A[1][2](%rdi),@C[1]
215         mov     $A[2][3](%rdi),@C[2]
216         mov     $A[3][4](%rdi),@C[3]
217         mov     $A[4][0](%rdi),@C[4]
218
219         xor     @D[1],@C[0]
220         xor     @D[2],@C[1]
221         xor     @D[3],@C[2]
222         xor     @D[4],@C[3]
223         xor     @D[0],@C[4]
224
225         rol     \$$rhotates[0][1],@C[0]
226         rol     \$$rhotates[1][2],@C[1]
227         rol     \$$rhotates[2][3],@C[2]
228         rol     \$$rhotates[3][4],@C[3]
229         rol     \$$rhotates[4][0],@C[4]
230
231         mov     @C[2],@T[0]
232         and     @C[3],@C[2]
233         xor     @C[1],@C[2]             #            C[1] ^ ( C[2] & C[3])
234         mov     @C[2],$A[2][1](%rsi)    # R[2][1] =  C[1] ^ ( C[2] & C[3])
235
236         mov     @C[4],@T[1]
237         not     @C[3]
238         and     @C[3],@C[4]
239         xor     @T[0],@C[4]             #            C[2] ^ ( C[4] & ~C[3])
240         mov     @C[4],$A[2][2](%rsi)    # R[2][2] =  C[2] ^ ( C[4] & ~C[3])
241
242         or      @C[1],@T[0]
243         xor     @C[0],@T[0]             #            C[0] ^ ( C[2] | C[1])
244         mov     @T[0],$A[2][0](%rsi)    # R[2][0] =  C[0] ^ ( C[2] | C[1])
245
246         and     @C[0],@C[1]
247         xor     @T[1],@C[1]             #            C[4] ^ ( C[1] & C[0])
248         mov     @C[1],$A[2][4](%rsi)    # R[2][4] =  C[4] ^ ( C[1] & C[0])
249
250         or      @T[1],@C[0]
251         xor     @C[3],@C[0]             #           ~C[3] ^ ( C[0] | C[4])
252         mov     @C[0],$A[2][3](%rsi)    # R[2][3] = ~C[3] ^ ( C[0] | C[4])
253
254
255         mov     $A[0][4](%rdi),@C[0]
256         mov     $A[1][0](%rdi),@C[1]
257         mov     $A[2][1](%rdi),@C[2]
258         mov     $A[3][2](%rdi),@C[3]
259         mov     $A[4][3](%rdi),@C[4]
260
261         xor     @D[4],@C[0]
262         xor     @D[0],@C[1]
263         xor     @D[1],@C[2]
264         xor     @D[2],@C[3]
265         xor     @D[3],@C[4]
266
267         rol     \$$rhotates[0][4],@C[0]
268         rol     \$$rhotates[1][0],@C[1]
269         rol     \$$rhotates[2][1],@C[2]
270         rol     \$$rhotates[3][2],@C[3]
271         rol     \$$rhotates[4][3],@C[4]
272
273         mov     @C[2],@T[0]
274         or      @C[3],@C[2]
275         xor     @C[1],@C[2]             #            C[1] ^ ( C[2] | C[3])
276         mov     @C[2],$A[3][1](%rsi)    # R[3][1] =  C[1] ^ ( C[2] | C[3])
277
278         mov     @C[4],@T[1]
279         not     @C[3]
280         or      @C[3],@C[4]
281         xor     @T[0],@C[4]             #            C[2] ^ ( C[4] | ~C[3])
282         mov     @C[4],$A[3][2](%rsi)    # R[3][2] =  C[2] ^ ( C[4] | ~C[3])
283
284         and     @C[1],@T[0]
285         xor     @C[0],@T[0]             #            C[0] ^ ( C[2] & C[1])
286         mov     @T[0],$A[3][0](%rsi)    # R[3][0] =  C[0] ^ ( C[2] & C[1])
287
288         or      @C[0],@C[1]
289         xor     @T[1],@C[1]             #            C[4] ^ ( C[1] | C[0])
290         mov     @C[1],$A[3][4](%rsi)    # R[3][4] =  C[4] ^ ( C[1] | C[0])
291
292         and     @T[1],@C[0]
293         xor     @C[3],@C[0]             #           ~C[3] ^ ( C[0] & C[4])
294         mov     @C[0],$A[3][3](%rsi)    # R[3][3] = ~C[3] ^ ( C[0] & C[4])
295
296
297         xor     $A[0][2](%rdi),@D[2]
298         xor     $A[1][3](%rdi),@D[3]
299         xor     $A[2][4](%rdi),@D[4]
300         xor     $A[3][0](%rdi),@D[0]
301         xor     $A[4][1](%rdi),@D[1]
302         xchg    %rsi,%rdi
303
304         rol     \$$rhotates[0][2],@D[2]
305         rol     \$$rhotates[1][3],@D[3]
306         rol     \$$rhotates[2][4],@D[4]
307         rol     \$$rhotates[3][0],@D[0]
308         rol     \$$rhotates[4][1],@D[1]
309 ___
310         @C = (@D[2],@D[3],@D[4],@D[0],@D[1]);
311 $code.=<<___;
312         mov     @C[0],@T[0]
313         and     @C[1],@C[0]
314         xor     @C[4],@C[0]             #            C[4] ^ ( C[0] & C[1])
315         mov     @C[0],$A[4][4](%rdi)    # R[4][4] =  C[4] ^ ( C[0] & C[1])
316
317         mov     @C[2],@T[1]
318         not     @C[1]
319         and     @C[1],@C[2]
320         xor     @T[0],@C[2]             #            C[0] ^ ( C[2] & ~C[1])
321         mov     @C[2],$A[4][0](%rdi)    # R[4][0] =  C[0] ^ ( C[2] & ~C[1])
322
323         or      @C[4],@T[0]
324         xor     @C[3],@T[0]             #            C[3] ^ ( C[0] | C[4])
325         mov     @T[0],$A[4][3](%rdi)    # R[4][3] =  C[3] ^ ( C[0] | C[4])
326
327         and     @C[3],@C[4]
328         xor     @T[1],@C[4]             #            C[2] ^ ( C[4] & C[3])
329         mov     @C[4],$A[4][2](%rdi)    # R[4][2] =  C[2] ^ ( C[4] & C[3])
330
331         or      @T[1],@C[3]
332         xor     @C[1],@C[3]             #           ~C[1] ^ ( C[2] | C[3])
333         mov     @C[3],$A[4][1](%rdi)    # R[4][1] = ~C[1] ^ ( C[2] | C[3])
334
335         mov     @C[0],@C[1]             # harmonize with the loop top
336         mov     @T[0],@C[0]
337
338         test    \$255,$iotas
339         jnz     .Loop
340
341         lea     -192($iotas),$iotas     # rewind iotas
342         ret
343 .size   __KeccakF1600,.-__KeccakF1600
344
345 .globl  KeccakF1600
346 .type   KeccakF1600,\@function
347 .align  32
348 KeccakF1600:
349         push    %rbx
350         push    %rbp
351         push    %r12
352         push    %r13
353         push    %r14
354         push    %r15
355
356         lea     100(%rdi),%rdi          # size optimization
357         sub     \$200,%rsp
358
359         notq    $A[0][1](%rdi)
360         notq    $A[0][2](%rdi)
361         notq    $A[1][3](%rdi)
362         notq    $A[2][2](%rdi)
363         notq    $A[3][2](%rdi)
364         notq    $A[4][0](%rdi)
365
366         lea     iotas(%rip),$iotas
367         lea     100(%rsp),%rsi          # size optimization
368
369         call    __KeccakF1600
370
371         notq    $A[0][1](%rdi)
372         notq    $A[0][2](%rdi)
373         notq    $A[1][3](%rdi)
374         notq    $A[2][2](%rdi)
375         notq    $A[3][2](%rdi)
376         notq    $A[4][0](%rdi)
377         lea     -100(%rdi),%rdi         # preserve A[][]
378
379         add     \$200,%rsp
380
381         pop     %r15
382         pop     %r14
383         pop     %r13
384         pop     %r12
385         pop     %rbp
386         pop     %rbx
387         ret
388 .size   KeccakF1600,.-KeccakF1600
389 ___
390
391 { my ($A_flat,$inp,$len,$bsz) = ("%rdi","%rsi","%rdx","%rcx");
392      ($A_flat,$inp) = ("%r8","%r9");
393 $code.=<<___;
394 .globl  SHA3_absorb
395 .type   SHA3_absorb,\@function
396 .align  32
397 SHA3_absorb:
398         push    %rbx
399         push    %rbp
400         push    %r12
401         push    %r13
402         push    %r14
403         push    %r15
404
405         lea     100(%rdi),%rdi          # size optimization
406         sub     \$232,%rsp
407
408         mov     %rsi,$inp
409         lea     100(%rsp),%rsi          # size optimization
410
411         notq    $A[0][1](%rdi)
412         notq    $A[0][2](%rdi)
413         notq    $A[1][3](%rdi)
414         notq    $A[2][2](%rdi)
415         notq    $A[3][2](%rdi)
416         notq    $A[4][0](%rdi)
417         lea     iotas(%rip),$iotas
418
419         mov     $bsz,216-100(%rsi)      # save bsz
420
421 .Loop_absorb:
422         cmp     $bsz,$len
423         jc      .Ldone_absorb
424
425         shr     \$3,$bsz
426         lea     -100(%rdi),$A_flat
427
428 .Lblock_absorb:
429         mov     ($inp),%rax
430         lea     8($inp),$inp
431         xor     ($A_flat),%rax
432         lea     8($A_flat),$A_flat
433         sub     \$8,$len
434         mov     %rax,-8($A_flat)
435         dec     $bsz
436         jnz     .Lblock_absorb
437
438         mov     $inp,200-100(%rsi)      # save inp
439         mov     $len,208-100(%rsi)      # save len
440         call    __KeccakF1600
441         mov     200-100(%rsi),$inp      # pull inp
442         mov     208-100(%rsi),$len      # pull len
443         mov     216-100(%rsi),$bsz      # pull bsz
444         jmp     .Loop_absorb
445
446 .align  32
447 .Ldone_absorb:
448         mov     $len,%rax               # return value
449
450         notq    $A[0][1](%rdi)
451         notq    $A[0][2](%rdi)
452         notq    $A[1][3](%rdi)
453         notq    $A[2][2](%rdi)
454         notq    $A[3][2](%rdi)
455         notq    $A[4][0](%rdi)
456
457         add     \$232,%rsp
458
459         pop     %r15
460         pop     %r14
461         pop     %r13
462         pop     %r12
463         pop     %rbp
464         pop     %rbx
465         ret
466 .size   SHA3_absorb,.-SHA3_absorb
467 ___
468 }
469 { my ($A_flat,$out,$len,$bsz) = ("%rdi","%rsi","%rdx","%rcx");
470      ($out,$len,$bsz) = ("%r12","%r13","%r14");
471
472 $code.=<<___;
473 .globl  SHA3_squeeze
474 .type   SHA3_squeeze,\@function
475 .align  32
476 SHA3_squeeze:
477         push    %r12
478         push    %r13
479         push    %r14
480
481         shr     \$3,%rcx
482         mov     $A_flat,%r8
483         mov     %rsi,$out
484         mov     %rdx,$len
485         mov     %rcx,$bsz
486         jmp     .Loop_squeeze
487
488 .align  32
489 .Loop_squeeze:
490         cmp     \$8,$len
491         jb      .Ltail_squeeze
492
493         mov     (%r8),%rax
494         lea     8(%r8),%r8
495         mov     %rax,($out)
496         lea     8($out),$out
497         sub     \$8,$len                # len -= 8
498         jz      .Ldone_squeeze
499
500         dec     %rcx                    # bsz--
501         jnz     .Loop_squeeze
502
503         call    KeccakF1600
504         mov     $A_flat,%r8
505         mov     $bsz,%rcx
506         jmp     .Loop_squeeze
507
508 .Ltail_squeeze:
509         mov     %r8, %rsi
510         mov     $out,%rdi
511         mov     $len,%rcx
512         .byte   0xf3,0xa4               # rep   movsb
513
514 .Ldone_squeeze:
515         pop     %r14
516         pop     %r13
517         pop     %r12
518         ret
519 .size   SHA3_squeeze,.-SHA3_squeeze
520 ___
521 }
522 $code.=<<___;
523 .align  256
524         .quad   0,0,0,0,0,0,0,0
525 .type   iotas,\@object
526 iotas:
527         .quad   0x0000000000000001
528         .quad   0x0000000000008082
529         .quad   0x800000000000808a
530         .quad   0x8000000080008000
531         .quad   0x000000000000808b
532         .quad   0x0000000080000001
533         .quad   0x8000000080008081
534         .quad   0x8000000000008009
535         .quad   0x000000000000008a
536         .quad   0x0000000000000088
537         .quad   0x0000000080008009
538         .quad   0x000000008000000a
539         .quad   0x000000008000808b
540         .quad   0x800000000000008b
541         .quad   0x8000000000008089
542         .quad   0x8000000000008003
543         .quad   0x8000000000008002
544         .quad   0x8000000000000080
545         .quad   0x000000000000800a
546         .quad   0x800000008000000a
547         .quad   0x8000000080008081
548         .quad   0x8000000000008080
549         .quad   0x0000000080000001
550         .quad   0x8000000080008008
551 .size   iotas,.-iotas
552 .asciz  "Keccak-1600 absorb and squeeze for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
553 ___
554
555 print $code;
556
557 close STDOUT;