x86_64 assembly pack: tolerate spaces in source directory name.
[openssl.git] / crypto / sha / asm / sha1-x86_64.pl
1 #! /usr/bin/env perl
2 # Copyright 2006-2016 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 # ====================================================================
11 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
12 # project. The module is, however, dual licensed under OpenSSL and
13 # CRYPTOGAMS licenses depending on where you obtain it. For further
14 # details see http://www.openssl.org/~appro/cryptogams/.
15 # ====================================================================
16 #
17 # sha1_block procedure for x86_64.
18 #
19 # It was brought to my attention that on EM64T compiler-generated code
20 # was far behind 32-bit assembler implementation. This is unlike on
21 # Opteron where compiler-generated code was only 15% behind 32-bit
22 # assembler, which originally made it hard to motivate the effort.
23 # There was suggestion to mechanically translate 32-bit code, but I
24 # dismissed it, reasoning that x86_64 offers enough register bank
25 # capacity to fully utilize SHA-1 parallelism. Therefore this fresh
26 # implementation:-) However! While 64-bit code does perform better
27 # on Opteron, I failed to beat 32-bit assembler on EM64T core. Well,
28 # x86_64 does offer larger *addressable* bank, but out-of-order core
29 # reaches for even more registers through dynamic aliasing, and EM64T
30 # core must have managed to run-time optimize even 32-bit code just as
31 # good as 64-bit one. Performance improvement is summarized in the
32 # following table:
33 #
34 #               gcc 3.4         32-bit asm      cycles/byte
35 # Opteron       +45%            +20%            6.8
36 # Xeon P4       +65%            +0%             9.9
37 # Core2         +60%            +10%            7.0
38
39 # August 2009.
40 #
41 # The code was revised to minimize code size and to maximize
42 # "distance" between instructions producing input to 'lea'
43 # instruction and the 'lea' instruction itself, which is essential
44 # for Intel Atom core.
45
46 # October 2010.
47 #
48 # Add SSSE3, Supplemental[!] SSE3, implementation. The idea behind it
49 # is to offload message schedule denoted by Wt in NIST specification,
50 # or Xupdate in OpenSSL source, to SIMD unit. See sha1-586.pl module
51 # for background and implementation details. The only difference from
52 # 32-bit code is that 64-bit code doesn't have to spill @X[] elements
53 # to free temporary registers.
54
55 # April 2011.
56 #
57 # Add AVX code path. See sha1-586.pl for further information.
58
59 # May 2013.
60 #
61 # Add AVX2+BMI code path. Initial attempt (utilizing BMI instructions
62 # and loading pair of consecutive blocks to 256-bit %ymm registers)
63 # did not provide impressive performance improvement till a crucial
64 # hint regarding the number of Xupdate iterations to pre-compute in
65 # advance was provided by Ilya Albrekht of Intel Corp.
66
67 # March 2014.
68 #
69 # Add support for Intel SHA Extensions.
70
71 ######################################################################
72 # Current performance is summarized in following table. Numbers are
73 # CPU clock cycles spent to process single byte (less is better).
74 #
75 #               x86_64          SSSE3           AVX[2]
76 # P4            9.05            -
77 # Opteron       6.26            -
78 # Core2         6.55            6.05/+8%        -
79 # Westmere      6.73            5.30/+27%       -
80 # Sandy Bridge  7.70            6.10/+26%       4.99/+54%
81 # Ivy Bridge    6.06            4.67/+30%       4.60/+32%
82 # Haswell       5.45            4.15/+31%       3.57/+53%
83 # Skylake       5.18            4.06/+28%       3.54/+46%
84 # Bulldozer     9.11            5.95/+53%
85 # VIA Nano      9.32            7.15/+30%
86 # Atom          10.3            9.17/+12%
87 # Silvermont    13.1(*)         9.37/+40%
88 #
89 # (*)   obviously suboptimal result, nothing was done about it,
90 #       because SSSE3 code is compiled unconditionally;
91
92 $flavour = shift;
93 $output  = shift;
94 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
95
96 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
97
98 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
99 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
100 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
101 die "can't locate x86_64-xlate.pl";
102
103 if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
104                 =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
105         $avx = ($1>=2.19) + ($1>=2.22);
106 }
107
108 if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
109            `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
110         $avx = ($1>=2.09) + ($1>=2.10);
111 }
112
113 if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
114            `ml64 2>&1` =~ /Version ([0-9]+)\./) {
115         $avx = ($1>=10) + ($1>=11);
116 }
117
118 if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([2-9]\.[0-9]+)/) {
119         $avx = ($2>=3.0) + ($2>3.0);
120 }
121
122 $shaext=1;      ### set to zero if compiling for 1.0.1
123 $avx=1          if (!$shaext && $avx);
124
125 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
126 *STDOUT=*OUT;
127
128 $ctx="%rdi";    # 1st arg
129 $inp="%rsi";    # 2nd arg
130 $num="%rdx";    # 3rd arg
131
132 # reassign arguments in order to produce more compact code
133 $ctx="%r8";
134 $inp="%r9";
135 $num="%r10";
136
137 $t0="%eax";
138 $t1="%ebx";
139 $t2="%ecx";
140 @xi=("%edx","%ebp","%r14d");
141 $A="%esi";
142 $B="%edi";
143 $C="%r11d";
144 $D="%r12d";
145 $E="%r13d";
146
147 @V=($A,$B,$C,$D,$E);
148
149 sub BODY_00_19 {
150 my ($i,$a,$b,$c,$d,$e)=@_;
151 my $j=$i+1;
152 $code.=<<___ if ($i==0);
153         mov     `4*$i`($inp),$xi[0]
154         bswap   $xi[0]
155 ___
156 $code.=<<___ if ($i<15);
157         mov     `4*$j`($inp),$xi[1]
158         mov     $d,$t0
159         mov     $xi[0],`4*$i`(%rsp)
160         mov     $a,$t2
161         bswap   $xi[1]
162         xor     $c,$t0
163         rol     \$5,$t2
164         and     $b,$t0
165         lea     0x5a827999($xi[0],$e),$e
166         add     $t2,$e
167         xor     $d,$t0
168         rol     \$30,$b
169         add     $t0,$e
170 ___
171 $code.=<<___ if ($i>=15);
172         xor     `4*($j%16)`(%rsp),$xi[1]
173         mov     $d,$t0
174         mov     $xi[0],`4*($i%16)`(%rsp)
175         mov     $a,$t2
176         xor     `4*(($j+2)%16)`(%rsp),$xi[1]
177         xor     $c,$t0
178         rol     \$5,$t2
179         xor     `4*(($j+8)%16)`(%rsp),$xi[1]
180         and     $b,$t0
181         lea     0x5a827999($xi[0],$e),$e
182         rol     \$30,$b
183         xor     $d,$t0
184         add     $t2,$e
185         rol     \$1,$xi[1]
186         add     $t0,$e
187 ___
188 push(@xi,shift(@xi));
189 }
190
191 sub BODY_20_39 {
192 my ($i,$a,$b,$c,$d,$e)=@_;
193 my $j=$i+1;
194 my $K=($i<40)?0x6ed9eba1:0xca62c1d6;
195 $code.=<<___ if ($i<79);
196         xor     `4*($j%16)`(%rsp),$xi[1]
197         mov     $b,$t0
198         `"mov   $xi[0],".4*($i%16)."(%rsp)"     if ($i<72)`
199         mov     $a,$t2
200         xor     `4*(($j+2)%16)`(%rsp),$xi[1]
201         xor     $d,$t0
202         rol     \$5,$t2
203         xor     `4*(($j+8)%16)`(%rsp),$xi[1]
204         lea     $K($xi[0],$e),$e
205         xor     $c,$t0
206         add     $t2,$e
207         rol     \$30,$b
208         add     $t0,$e
209         rol     \$1,$xi[1]
210 ___
211 $code.=<<___ if ($i==79);
212         mov     $b,$t0
213         mov     $a,$t2
214         xor     $d,$t0
215         lea     $K($xi[0],$e),$e
216         rol     \$5,$t2
217         xor     $c,$t0
218         add     $t2,$e
219         rol     \$30,$b
220         add     $t0,$e
221 ___
222 push(@xi,shift(@xi));
223 }
224
225 sub BODY_40_59 {
226 my ($i,$a,$b,$c,$d,$e)=@_;
227 my $j=$i+1;
228 $code.=<<___;
229         xor     `4*($j%16)`(%rsp),$xi[1]
230         mov     $d,$t0
231         mov     $xi[0],`4*($i%16)`(%rsp)
232         mov     $d,$t1
233         xor     `4*(($j+2)%16)`(%rsp),$xi[1]
234         and     $c,$t0
235         mov     $a,$t2
236         xor     `4*(($j+8)%16)`(%rsp),$xi[1]
237         lea     0x8f1bbcdc($xi[0],$e),$e
238         xor     $c,$t1
239         rol     \$5,$t2
240         add     $t0,$e
241         rol     \$1,$xi[1]
242         and     $b,$t1
243         add     $t2,$e
244         rol     \$30,$b
245         add     $t1,$e
246 ___
247 push(@xi,shift(@xi));
248 }
249
250 $code.=<<___;
251 .text
252 .extern OPENSSL_ia32cap_P
253
254 .globl  sha1_block_data_order
255 .type   sha1_block_data_order,\@function,3
256 .align  16
257 sha1_block_data_order:
258         mov     OPENSSL_ia32cap_P+0(%rip),%r9d
259         mov     OPENSSL_ia32cap_P+4(%rip),%r8d
260         mov     OPENSSL_ia32cap_P+8(%rip),%r10d
261         test    \$`1<<9`,%r8d           # check SSSE3 bit
262         jz      .Lialu
263 ___
264 $code.=<<___ if ($shaext);
265         test    \$`1<<29`,%r10d         # check SHA bit 
266         jnz     _shaext_shortcut
267 ___
268 $code.=<<___ if ($avx>1);
269         and     \$`1<<3|1<<5|1<<8`,%r10d        # check AVX2+BMI1+BMI2
270         cmp     \$`1<<3|1<<5|1<<8`,%r10d
271         je      _avx2_shortcut
272 ___
273 $code.=<<___ if ($avx);
274         and     \$`1<<28`,%r8d          # mask AVX bit
275         and     \$`1<<30`,%r9d          # mask "Intel CPU" bit
276         or      %r9d,%r8d
277         cmp     \$`1<<28|1<<30`,%r8d
278         je      _avx_shortcut
279 ___
280 $code.=<<___;
281         jmp     _ssse3_shortcut
282
283 .align  16
284 .Lialu:
285         mov     %rsp,%rax
286         push    %rbx
287         push    %rbp
288         push    %r12
289         push    %r13
290         push    %r14
291         mov     %rdi,$ctx       # reassigned argument
292         sub     \$`8+16*4`,%rsp
293         mov     %rsi,$inp       # reassigned argument
294         and     \$-64,%rsp
295         mov     %rdx,$num       # reassigned argument
296         mov     %rax,`16*4`(%rsp)
297 .Lprologue:
298
299         mov     0($ctx),$A
300         mov     4($ctx),$B
301         mov     8($ctx),$C
302         mov     12($ctx),$D
303         mov     16($ctx),$E
304         jmp     .Lloop
305
306 .align  16
307 .Lloop:
308 ___
309 for($i=0;$i<20;$i++)    { &BODY_00_19($i,@V); unshift(@V,pop(@V)); }
310 for(;$i<40;$i++)        { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
311 for(;$i<60;$i++)        { &BODY_40_59($i,@V); unshift(@V,pop(@V)); }
312 for(;$i<80;$i++)        { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
313 $code.=<<___;
314         add     0($ctx),$A
315         add     4($ctx),$B
316         add     8($ctx),$C
317         add     12($ctx),$D
318         add     16($ctx),$E
319         mov     $A,0($ctx)
320         mov     $B,4($ctx)
321         mov     $C,8($ctx)
322         mov     $D,12($ctx)
323         mov     $E,16($ctx)
324
325         sub     \$1,$num
326         lea     `16*4`($inp),$inp
327         jnz     .Lloop
328
329         mov     `16*4`(%rsp),%rsi
330         mov     -40(%rsi),%r14
331         mov     -32(%rsi),%r13
332         mov     -24(%rsi),%r12
333         mov     -16(%rsi),%rbp
334         mov     -8(%rsi),%rbx
335         lea     (%rsi),%rsp
336 .Lepilogue:
337         ret
338 .size   sha1_block_data_order,.-sha1_block_data_order
339 ___
340 if ($shaext) {{{
341 ######################################################################
342 # Intel SHA Extensions implementation of SHA1 update function.
343 #
344 my ($ctx,$inp,$num)=("%rdi","%rsi","%rdx");
345 my ($ABCD,$E,$E_,$BSWAP,$ABCD_SAVE,$E_SAVE)=map("%xmm$_",(0..3,8,9));
346 my @MSG=map("%xmm$_",(4..7));
347
348 $code.=<<___;
349 .type   sha1_block_data_order_shaext,\@function,3
350 .align  32
351 sha1_block_data_order_shaext:
352 _shaext_shortcut:
353 ___
354 $code.=<<___ if ($win64);
355         lea     `-8-4*16`(%rsp),%rsp
356         movaps  %xmm6,-8-4*16(%rax)
357         movaps  %xmm7,-8-3*16(%rax)
358         movaps  %xmm8,-8-2*16(%rax)
359         movaps  %xmm9,-8-1*16(%rax)
360 .Lprologue_shaext:
361 ___
362 $code.=<<___;
363         movdqu  ($ctx),$ABCD
364         movd    16($ctx),$E
365         movdqa  K_XX_XX+0xa0(%rip),$BSWAP       # byte-n-word swap
366
367         movdqu  ($inp),@MSG[0]
368         pshufd  \$0b00011011,$ABCD,$ABCD        # flip word order
369         movdqu  0x10($inp),@MSG[1]
370         pshufd  \$0b00011011,$E,$E              # flip word order
371         movdqu  0x20($inp),@MSG[2]
372         pshufb  $BSWAP,@MSG[0]
373         movdqu  0x30($inp),@MSG[3]
374         pshufb  $BSWAP,@MSG[1]
375         pshufb  $BSWAP,@MSG[2]
376         movdqa  $E,$E_SAVE                      # offload $E
377         pshufb  $BSWAP,@MSG[3]
378         jmp     .Loop_shaext
379
380 .align  16
381 .Loop_shaext:
382         dec             $num
383         lea             0x40($inp),%rax         # next input block
384         paddd           @MSG[0],$E
385         cmovne          %rax,$inp
386         movdqa          $ABCD,$ABCD_SAVE        # offload $ABCD
387 ___
388 for($i=0;$i<20-4;$i+=2) {
389 $code.=<<___;
390         sha1msg1        @MSG[1],@MSG[0]
391         movdqa          $ABCD,$E_
392         sha1rnds4       \$`int($i/5)`,$E,$ABCD  # 0-3...
393         sha1nexte       @MSG[1],$E_
394         pxor            @MSG[2],@MSG[0]
395         sha1msg1        @MSG[2],@MSG[1]
396         sha1msg2        @MSG[3],@MSG[0]
397
398         movdqa          $ABCD,$E
399         sha1rnds4       \$`int(($i+1)/5)`,$E_,$ABCD
400         sha1nexte       @MSG[2],$E
401         pxor            @MSG[3],@MSG[1]
402         sha1msg2        @MSG[0],@MSG[1]
403 ___
404         push(@MSG,shift(@MSG)); push(@MSG,shift(@MSG));
405 }
406 $code.=<<___;
407         movdqu          ($inp),@MSG[0]
408         movdqa          $ABCD,$E_
409         sha1rnds4       \$3,$E,$ABCD            # 64-67
410         sha1nexte       @MSG[1],$E_
411         movdqu          0x10($inp),@MSG[1]
412         pshufb          $BSWAP,@MSG[0]
413
414         movdqa          $ABCD,$E
415         sha1rnds4       \$3,$E_,$ABCD           # 68-71
416         sha1nexte       @MSG[2],$E
417         movdqu          0x20($inp),@MSG[2]
418         pshufb          $BSWAP,@MSG[1]
419
420         movdqa          $ABCD,$E_
421         sha1rnds4       \$3,$E,$ABCD            # 72-75
422         sha1nexte       @MSG[3],$E_
423         movdqu          0x30($inp),@MSG[3]
424         pshufb          $BSWAP,@MSG[2]
425
426         movdqa          $ABCD,$E
427         sha1rnds4       \$3,$E_,$ABCD           # 76-79
428         sha1nexte       $E_SAVE,$E
429         pshufb          $BSWAP,@MSG[3]
430
431         paddd           $ABCD_SAVE,$ABCD
432         movdqa          $E,$E_SAVE              # offload $E
433
434         jnz             .Loop_shaext
435
436         pshufd  \$0b00011011,$ABCD,$ABCD
437         pshufd  \$0b00011011,$E,$E
438         movdqu  $ABCD,($ctx)
439         movd    $E,16($ctx)
440 ___
441 $code.=<<___ if ($win64);
442         movaps  -8-4*16(%rax),%xmm6
443         movaps  -8-3*16(%rax),%xmm7
444         movaps  -8-2*16(%rax),%xmm8
445         movaps  -8-1*16(%rax),%xmm9
446         mov     %rax,%rsp
447 .Lepilogue_shaext:
448 ___
449 $code.=<<___;
450         ret
451 .size   sha1_block_data_order_shaext,.-sha1_block_data_order_shaext
452 ___
453 }}}
454 {{{
455 my $Xi=4;
456 my @X=map("%xmm$_",(4..7,0..3));
457 my @Tx=map("%xmm$_",(8..10));
458 my $Kx="%xmm11";
459 my @V=($A,$B,$C,$D,$E)=("%eax","%ebx","%ecx","%edx","%ebp");    # size optimization
460 my @T=("%esi","%edi");
461 my $j=0;
462 my $rx=0;
463 my $K_XX_XX="%r11";
464
465 my $_rol=sub { &rol(@_) };
466 my $_ror=sub { &ror(@_) };
467
468 { my $sn;
469 sub align32() {
470   ++$sn;
471 $code.=<<___;
472         jmp     .Lalign32_$sn   # see "Decoded ICache" in manual
473 .align  32
474 .Lalign32_$sn:
475 ___
476 }
477 }
478
479 $code.=<<___;
480 .type   sha1_block_data_order_ssse3,\@function,3
481 .align  16
482 sha1_block_data_order_ssse3:
483 _ssse3_shortcut:
484         mov     %rsp,%rax
485         push    %rbx
486         push    %rbp
487         push    %r12
488         push    %r13            # redundant, done to share Win64 SE handler
489         push    %r14
490         lea     `-64-($win64?6*16:0)`(%rsp),%rsp
491 ___
492 $code.=<<___ if ($win64);
493         movaps  %xmm6,-40-6*16(%rax)
494         movaps  %xmm7,-40-5*16(%rax)
495         movaps  %xmm8,-40-4*16(%rax)
496         movaps  %xmm9,-40-3*16(%rax)
497         movaps  %xmm10,-40-2*16(%rax)
498         movaps  %xmm11,-40-1*16(%rax)
499 .Lprologue_ssse3:
500 ___
501 $code.=<<___;
502         mov     %rax,%r14       # original %rsp
503         and     \$-64,%rsp
504         mov     %rdi,$ctx       # reassigned argument
505         mov     %rsi,$inp       # reassigned argument
506         mov     %rdx,$num       # reassigned argument
507
508         shl     \$6,$num
509         add     $inp,$num
510         lea     K_XX_XX+64(%rip),$K_XX_XX
511
512         mov     0($ctx),$A              # load context
513         mov     4($ctx),$B
514         mov     8($ctx),$C
515         mov     12($ctx),$D
516         mov     $B,@T[0]                # magic seed
517         mov     16($ctx),$E
518         mov     $C,@T[1]
519         xor     $D,@T[1]
520         and     @T[1],@T[0]
521
522         movdqa  64($K_XX_XX),@X[2]      # pbswap mask
523         movdqa  -64($K_XX_XX),@Tx[1]    # K_00_19
524         movdqu  0($inp),@X[-4&7]        # load input to %xmm[0-3]
525         movdqu  16($inp),@X[-3&7]
526         movdqu  32($inp),@X[-2&7]
527         movdqu  48($inp),@X[-1&7]
528         pshufb  @X[2],@X[-4&7]          # byte swap
529         pshufb  @X[2],@X[-3&7]
530         pshufb  @X[2],@X[-2&7]
531         add     \$64,$inp
532         paddd   @Tx[1],@X[-4&7]         # add K_00_19
533         pshufb  @X[2],@X[-1&7]
534         paddd   @Tx[1],@X[-3&7]
535         paddd   @Tx[1],@X[-2&7]
536         movdqa  @X[-4&7],0(%rsp)        # X[]+K xfer to IALU
537         psubd   @Tx[1],@X[-4&7]         # restore X[]
538         movdqa  @X[-3&7],16(%rsp)
539         psubd   @Tx[1],@X[-3&7]
540         movdqa  @X[-2&7],32(%rsp)
541         psubd   @Tx[1],@X[-2&7]
542         jmp     .Loop_ssse3
543 ___
544
545 sub AUTOLOAD()          # thunk [simplified] 32-bit style perlasm
546 { my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
547   my $arg = pop;
548     $arg = "\$$arg" if ($arg*1 eq $arg);
549     $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
550 }
551
552 sub Xupdate_ssse3_16_31()               # recall that $Xi starts wtih 4
553 { use integer;
554   my $body = shift;
555   my @insns = (&$body,&$body,&$body,&$body);    # 40 instructions
556   my ($a,$b,$c,$d,$e);
557
558          eval(shift(@insns));           # ror
559         &pshufd (@X[0],@X[-4&7],0xee);  # was &movdqa   (@X[0],@X[-3&7]);
560          eval(shift(@insns));
561         &movdqa (@Tx[0],@X[-1&7]);
562           &paddd        (@Tx[1],@X[-1&7]);
563          eval(shift(@insns));
564          eval(shift(@insns));
565
566         &punpcklqdq(@X[0],@X[-3&7]);    # compose "X[-14]" in "X[0]", was &palignr(@X[0],@X[-4&7],8);
567          eval(shift(@insns));
568          eval(shift(@insns));           # rol
569          eval(shift(@insns));
570         &psrldq (@Tx[0],4);             # "X[-3]", 3 dwords
571          eval(shift(@insns));
572          eval(shift(@insns));
573
574         &pxor   (@X[0],@X[-4&7]);       # "X[0]"^="X[-16]"
575          eval(shift(@insns));
576          eval(shift(@insns));           # ror
577         &pxor   (@Tx[0],@X[-2&7]);      # "X[-3]"^"X[-8]"
578          eval(shift(@insns));
579          eval(shift(@insns));
580          eval(shift(@insns));
581
582         &pxor   (@X[0],@Tx[0]);         # "X[0]"^="X[-3]"^"X[-8]"
583          eval(shift(@insns));
584          eval(shift(@insns));           # rol
585           &movdqa       (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
586          eval(shift(@insns));
587          eval(shift(@insns));
588
589         &movdqa (@Tx[2],@X[0]);
590          eval(shift(@insns));
591          eval(shift(@insns));
592          eval(shift(@insns));           # ror
593         &movdqa (@Tx[0],@X[0]);
594          eval(shift(@insns));
595
596         &pslldq (@Tx[2],12);            # "X[0]"<<96, extract one dword
597         &paddd  (@X[0],@X[0]);
598          eval(shift(@insns));
599          eval(shift(@insns));
600
601         &psrld  (@Tx[0],31);
602          eval(shift(@insns));
603          eval(shift(@insns));           # rol
604          eval(shift(@insns));
605         &movdqa (@Tx[1],@Tx[2]);
606          eval(shift(@insns));
607          eval(shift(@insns));
608
609         &psrld  (@Tx[2],30);
610          eval(shift(@insns));
611          eval(shift(@insns));           # ror
612         &por    (@X[0],@Tx[0]);         # "X[0]"<<<=1
613          eval(shift(@insns));
614          eval(shift(@insns));
615          eval(shift(@insns));
616
617         &pslld  (@Tx[1],2);
618         &pxor   (@X[0],@Tx[2]);
619          eval(shift(@insns));
620           &movdqa       (@Tx[2],eval(2*16*(($Xi)/5)-64)."($K_XX_XX)");  # K_XX_XX
621          eval(shift(@insns));           # rol
622          eval(shift(@insns));
623          eval(shift(@insns));
624
625         &pxor   (@X[0],@Tx[1]);         # "X[0]"^=("X[0]">>96)<<<2
626         &pshufd (@Tx[1],@X[-1&7],0xee)  if ($Xi==7);    # was &movdqa   (@Tx[0],@X[-1&7]) in Xupdate_ssse3_32_79
627
628          foreach (@insns) { eval; }     # remaining instructions [if any]
629
630   $Xi++;        push(@X,shift(@X));     # "rotate" X[]
631                 push(@Tx,shift(@Tx));
632 }
633
634 sub Xupdate_ssse3_32_79()
635 { use integer;
636   my $body = shift;
637   my @insns = (&$body,&$body,&$body,&$body);    # 32 to 44 instructions
638   my ($a,$b,$c,$d,$e);
639
640          eval(shift(@insns))            if ($Xi==8);
641         &pxor   (@X[0],@X[-4&7]);       # "X[0]"="X[-32]"^"X[-16]"
642          eval(shift(@insns))            if ($Xi==8);
643          eval(shift(@insns));           # body_20_39
644          eval(shift(@insns));
645          eval(shift(@insns))            if (@insns[1] =~ /_ror/);
646          eval(shift(@insns))            if (@insns[0] =~ /_ror/);
647         &punpcklqdq(@Tx[0],@X[-1&7]);   # compose "X[-6]", was &palignr(@Tx[0],@X[-2&7],8);
648          eval(shift(@insns));
649          eval(shift(@insns));           # rol
650
651         &pxor   (@X[0],@X[-7&7]);       # "X[0]"^="X[-28]"
652          eval(shift(@insns));
653          eval(shift(@insns));
654         if ($Xi%5) {
655           &movdqa       (@Tx[2],@Tx[1]);# "perpetuate" K_XX_XX...
656         } else {                        # ... or load next one
657           &movdqa       (@Tx[2],eval(2*16*($Xi/5)-64)."($K_XX_XX)");
658         }
659          eval(shift(@insns));           # ror
660           &paddd        (@Tx[1],@X[-1&7]);
661          eval(shift(@insns));
662
663         &pxor   (@X[0],@Tx[0]);         # "X[0]"^="X[-6]"
664          eval(shift(@insns));           # body_20_39
665          eval(shift(@insns));
666          eval(shift(@insns));
667          eval(shift(@insns));           # rol
668          eval(shift(@insns))            if (@insns[0] =~ /_ror/);
669
670         &movdqa (@Tx[0],@X[0]);
671          eval(shift(@insns));
672          eval(shift(@insns));
673           &movdqa       (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
674          eval(shift(@insns));           # ror
675          eval(shift(@insns));
676          eval(shift(@insns));           # body_20_39
677
678         &pslld  (@X[0],2);
679          eval(shift(@insns));
680          eval(shift(@insns));
681         &psrld  (@Tx[0],30);
682          eval(shift(@insns))            if (@insns[0] =~ /_rol/);# rol
683          eval(shift(@insns));
684          eval(shift(@insns));
685          eval(shift(@insns));           # ror
686
687         &por    (@X[0],@Tx[0]);         # "X[0]"<<<=2
688          eval(shift(@insns));
689          eval(shift(@insns));           # body_20_39
690          eval(shift(@insns))            if (@insns[1] =~ /_rol/);
691          eval(shift(@insns))            if (@insns[0] =~ /_rol/);
692           &pshufd(@Tx[1],@X[-1&7],0xee) if ($Xi<19);    # was &movdqa   (@Tx[1],@X[0])
693          eval(shift(@insns));
694          eval(shift(@insns));           # rol
695          eval(shift(@insns));
696          eval(shift(@insns));
697          eval(shift(@insns));           # rol
698          eval(shift(@insns));
699
700          foreach (@insns) { eval; }     # remaining instructions
701
702   $Xi++;        push(@X,shift(@X));     # "rotate" X[]
703                 push(@Tx,shift(@Tx));
704 }
705
706 sub Xuplast_ssse3_80()
707 { use integer;
708   my $body = shift;
709   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
710   my ($a,$b,$c,$d,$e);
711
712          eval(shift(@insns));
713          eval(shift(@insns));
714          eval(shift(@insns));
715          eval(shift(@insns));
716           &paddd        (@Tx[1],@X[-1&7]);
717          eval(shift(@insns));
718          eval(shift(@insns));
719
720           &movdqa       (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU
721
722          foreach (@insns) { eval; }             # remaining instructions
723
724         &cmp    ($inp,$num);
725         &je     (".Ldone_ssse3");
726
727         unshift(@Tx,pop(@Tx));
728
729         &movdqa (@X[2],"64($K_XX_XX)");         # pbswap mask
730         &movdqa (@Tx[1],"-64($K_XX_XX)");       # K_00_19
731         &movdqu (@X[-4&7],"0($inp)");           # load input
732         &movdqu (@X[-3&7],"16($inp)");
733         &movdqu (@X[-2&7],"32($inp)");
734         &movdqu (@X[-1&7],"48($inp)");
735         &pshufb (@X[-4&7],@X[2]);               # byte swap
736         &add    ($inp,64);
737
738   $Xi=0;
739 }
740
741 sub Xloop_ssse3()
742 { use integer;
743   my $body = shift;
744   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
745   my ($a,$b,$c,$d,$e);
746
747          eval(shift(@insns));
748          eval(shift(@insns));
749          eval(shift(@insns));
750         &pshufb (@X[($Xi-3)&7],@X[2]);
751          eval(shift(@insns));
752          eval(shift(@insns));
753          eval(shift(@insns));
754          eval(shift(@insns));
755         &paddd  (@X[($Xi-4)&7],@Tx[1]);
756          eval(shift(@insns));
757          eval(shift(@insns));
758          eval(shift(@insns));
759          eval(shift(@insns));
760         &movdqa (eval(16*$Xi)."(%rsp)",@X[($Xi-4)&7]);  # X[]+K xfer to IALU
761          eval(shift(@insns));
762          eval(shift(@insns));
763          eval(shift(@insns));
764          eval(shift(@insns));
765         &psubd  (@X[($Xi-4)&7],@Tx[1]);
766
767         foreach (@insns) { eval; }
768   $Xi++;
769 }
770
771 sub Xtail_ssse3()
772 { use integer;
773   my $body = shift;
774   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
775   my ($a,$b,$c,$d,$e);
776
777         foreach (@insns) { eval; }
778 }
779
780 sub body_00_19 () {     # ((c^d)&b)^d
781         # on start @T[0]=(c^d)&b
782         return &body_20_39() if ($rx==19); $rx++;
783         (
784         '($a,$b,$c,$d,$e)=@V;'.
785         '&$_ror ($b,$j?7:2)',   # $b>>>2
786         '&xor   (@T[0],$d)',
787         '&mov   (@T[1],$a)',    # $b for next round
788
789         '&add   ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer
790         '&xor   ($b,$c)',       # $c^$d for next round
791
792         '&$_rol ($a,5)',
793         '&add   ($e,@T[0])',
794         '&and   (@T[1],$b)',    # ($b&($c^$d)) for next round
795
796         '&xor   ($b,$c)',       # restore $b
797         '&add   ($e,$a);'       .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
798         );
799 }
800
801 sub body_20_39 () {     # b^d^c
802         # on entry @T[0]=b^d
803         return &body_40_59() if ($rx==39); $rx++;
804         (
805         '($a,$b,$c,$d,$e)=@V;'.
806         '&add   ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer
807         '&xor   (@T[0],$d)      if($j==19);'.
808         '&xor   (@T[0],$c)      if($j> 19)',    # ($b^$d^$c)
809         '&mov   (@T[1],$a)',    # $b for next round
810
811         '&$_rol ($a,5)',
812         '&add   ($e,@T[0])',
813         '&xor   (@T[1],$c)      if ($j< 79)',   # $b^$d for next round
814
815         '&$_ror ($b,7)',        # $b>>>2
816         '&add   ($e,$a);'       .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
817         );
818 }
819
820 sub body_40_59 () {     # ((b^c)&(c^d))^c
821         # on entry @T[0]=(b^c), (c^=d)
822         $rx++;
823         (
824         '($a,$b,$c,$d,$e)=@V;'.
825         '&add   ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer
826         '&and   (@T[0],$c)      if ($j>=40)',   # (b^c)&(c^d)
827         '&xor   ($c,$d)         if ($j>=40)',   # restore $c
828
829         '&$_ror ($b,7)',        # $b>>>2
830         '&mov   (@T[1],$a)',    # $b for next round
831         '&xor   (@T[0],$c)',
832
833         '&$_rol ($a,5)',
834         '&add   ($e,@T[0])',
835         '&xor   (@T[1],$c)      if ($j==59);'.
836         '&xor   (@T[1],$b)      if ($j< 59)',   # b^c for next round
837
838         '&xor   ($b,$c)         if ($j< 59)',   # c^d for next round
839         '&add   ($e,$a);'       .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
840         );
841 }
842 $code.=<<___;
843 .align  16
844 .Loop_ssse3:
845 ___
846         &Xupdate_ssse3_16_31(\&body_00_19);
847         &Xupdate_ssse3_16_31(\&body_00_19);
848         &Xupdate_ssse3_16_31(\&body_00_19);
849         &Xupdate_ssse3_16_31(\&body_00_19);
850         &Xupdate_ssse3_32_79(\&body_00_19);
851         &Xupdate_ssse3_32_79(\&body_20_39);
852         &Xupdate_ssse3_32_79(\&body_20_39);
853         &Xupdate_ssse3_32_79(\&body_20_39);
854         &Xupdate_ssse3_32_79(\&body_20_39);
855         &Xupdate_ssse3_32_79(\&body_20_39);
856         &Xupdate_ssse3_32_79(\&body_40_59);
857         &Xupdate_ssse3_32_79(\&body_40_59);
858         &Xupdate_ssse3_32_79(\&body_40_59);
859         &Xupdate_ssse3_32_79(\&body_40_59);
860         &Xupdate_ssse3_32_79(\&body_40_59);
861         &Xupdate_ssse3_32_79(\&body_20_39);
862         &Xuplast_ssse3_80(\&body_20_39);        # can jump to "done"
863
864                                 $saved_j=$j; @saved_V=@V;
865
866         &Xloop_ssse3(\&body_20_39);
867         &Xloop_ssse3(\&body_20_39);
868         &Xloop_ssse3(\&body_20_39);
869
870 $code.=<<___;
871         add     0($ctx),$A                      # update context
872         add     4($ctx),@T[0]
873         add     8($ctx),$C
874         add     12($ctx),$D
875         mov     $A,0($ctx)
876         add     16($ctx),$E
877         mov     @T[0],4($ctx)
878         mov     @T[0],$B                        # magic seed
879         mov     $C,8($ctx)
880         mov     $C,@T[1]
881         mov     $D,12($ctx)
882         xor     $D,@T[1]
883         mov     $E,16($ctx)
884         and     @T[1],@T[0]
885         jmp     .Loop_ssse3
886
887 .align  16
888 .Ldone_ssse3:
889 ___
890                                 $j=$saved_j; @V=@saved_V;
891
892         &Xtail_ssse3(\&body_20_39);
893         &Xtail_ssse3(\&body_20_39);
894         &Xtail_ssse3(\&body_20_39);
895
896 $code.=<<___;
897         add     0($ctx),$A                      # update context
898         add     4($ctx),@T[0]
899         add     8($ctx),$C
900         mov     $A,0($ctx)
901         add     12($ctx),$D
902         mov     @T[0],4($ctx)
903         add     16($ctx),$E
904         mov     $C,8($ctx)
905         mov     $D,12($ctx)
906         mov     $E,16($ctx)
907 ___
908 $code.=<<___ if ($win64);
909         movaps  -40-6*16(%r14),%xmm6
910         movaps  -40-5*16(%r14),%xmm7
911         movaps  -40-4*16(%r14),%xmm8
912         movaps  -40-3*16(%r14),%xmm9
913         movaps  -40-2*16(%r14),%xmm10
914         movaps  -40-1*16(%r14),%xmm11
915 ___
916 $code.=<<___;
917         lea     (%r14),%rsi
918         mov     -40(%rsi),%r14
919         mov     -32(%rsi),%r13
920         mov     -24(%rsi),%r12
921         mov     -16(%rsi),%rbp
922         mov     -8(%rsi),%rbx
923         lea     (%rsi),%rsp
924 .Lepilogue_ssse3:
925         ret
926 .size   sha1_block_data_order_ssse3,.-sha1_block_data_order_ssse3
927 ___
928
929 if ($avx) {
930 $Xi=4;                          # reset variables
931 @X=map("%xmm$_",(4..7,0..3));
932 @Tx=map("%xmm$_",(8..10));
933 $j=0;
934 $rx=0;
935
936 my $done_avx_label=".Ldone_avx";
937
938 my $_rol=sub { &shld(@_[0],@_) };
939 my $_ror=sub { &shrd(@_[0],@_) };
940
941 $code.=<<___;
942 .type   sha1_block_data_order_avx,\@function,3
943 .align  16
944 sha1_block_data_order_avx:
945 _avx_shortcut:
946         mov     %rsp,%rax
947         push    %rbx
948         push    %rbp
949         push    %r12
950         push    %r13            # redundant, done to share Win64 SE handler
951         push    %r14
952         lea     `-64-($win64?6*16:0)`(%rsp),%rsp
953         vzeroupper
954 ___
955 $code.=<<___ if ($win64);
956         vmovaps %xmm6,-40-6*16(%rax)
957         vmovaps %xmm7,-40-5*16(%rax)
958         vmovaps %xmm8,-40-4*16(%rax)
959         vmovaps %xmm9,-40-3*16(%rax)
960         vmovaps %xmm10,-40-2*16(%rax)
961         vmovaps %xmm11,-40-1*16(%rax)
962 .Lprologue_avx:
963 ___
964 $code.=<<___;
965         mov     %rax,%r14       # original %rsp
966         and     \$-64,%rsp
967         mov     %rdi,$ctx       # reassigned argument
968         mov     %rsi,$inp       # reassigned argument
969         mov     %rdx,$num       # reassigned argument
970
971         shl     \$6,$num
972         add     $inp,$num
973         lea     K_XX_XX+64(%rip),$K_XX_XX
974
975         mov     0($ctx),$A              # load context
976         mov     4($ctx),$B
977         mov     8($ctx),$C
978         mov     12($ctx),$D
979         mov     $B,@T[0]                # magic seed
980         mov     16($ctx),$E
981         mov     $C,@T[1]
982         xor     $D,@T[1]
983         and     @T[1],@T[0]
984
985         vmovdqa 64($K_XX_XX),@X[2]      # pbswap mask
986         vmovdqa -64($K_XX_XX),$Kx       # K_00_19
987         vmovdqu 0($inp),@X[-4&7]        # load input to %xmm[0-3]
988         vmovdqu 16($inp),@X[-3&7]
989         vmovdqu 32($inp),@X[-2&7]
990         vmovdqu 48($inp),@X[-1&7]
991         vpshufb @X[2],@X[-4&7],@X[-4&7] # byte swap
992         add     \$64,$inp
993         vpshufb @X[2],@X[-3&7],@X[-3&7]
994         vpshufb @X[2],@X[-2&7],@X[-2&7]
995         vpshufb @X[2],@X[-1&7],@X[-1&7]
996         vpaddd  $Kx,@X[-4&7],@X[0]      # add K_00_19
997         vpaddd  $Kx,@X[-3&7],@X[1]
998         vpaddd  $Kx,@X[-2&7],@X[2]
999         vmovdqa @X[0],0(%rsp)           # X[]+K xfer to IALU
1000         vmovdqa @X[1],16(%rsp)
1001         vmovdqa @X[2],32(%rsp)
1002         jmp     .Loop_avx
1003 ___
1004
1005 sub Xupdate_avx_16_31()         # recall that $Xi starts wtih 4
1006 { use integer;
1007   my $body = shift;
1008   my @insns = (&$body,&$body,&$body,&$body);    # 40 instructions
1009   my ($a,$b,$c,$d,$e);
1010
1011          eval(shift(@insns));
1012          eval(shift(@insns));
1013         &vpalignr(@X[0],@X[-3&7],@X[-4&7],8);   # compose "X[-14]" in "X[0]"
1014          eval(shift(@insns));
1015          eval(shift(@insns));
1016
1017           &vpaddd       (@Tx[1],$Kx,@X[-1&7]);
1018          eval(shift(@insns));
1019          eval(shift(@insns));
1020         &vpsrldq(@Tx[0],@X[-1&7],4);            # "X[-3]", 3 dwords
1021          eval(shift(@insns));
1022          eval(shift(@insns));
1023         &vpxor  (@X[0],@X[0],@X[-4&7]);         # "X[0]"^="X[-16]"
1024          eval(shift(@insns));
1025          eval(shift(@insns));
1026
1027         &vpxor  (@Tx[0],@Tx[0],@X[-2&7]);       # "X[-3]"^"X[-8]"
1028          eval(shift(@insns));
1029          eval(shift(@insns));
1030          eval(shift(@insns));
1031          eval(shift(@insns));
1032
1033         &vpxor  (@X[0],@X[0],@Tx[0]);           # "X[0]"^="X[-3]"^"X[-8]"
1034          eval(shift(@insns));
1035          eval(shift(@insns));
1036           &vmovdqa      (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
1037          eval(shift(@insns));
1038          eval(shift(@insns));
1039
1040         &vpsrld (@Tx[0],@X[0],31);
1041          eval(shift(@insns));
1042          eval(shift(@insns));
1043          eval(shift(@insns));
1044          eval(shift(@insns));
1045
1046         &vpslldq(@Tx[2],@X[0],12);              # "X[0]"<<96, extract one dword
1047         &vpaddd (@X[0],@X[0],@X[0]);
1048          eval(shift(@insns));
1049          eval(shift(@insns));
1050          eval(shift(@insns));
1051          eval(shift(@insns));
1052
1053         &vpsrld (@Tx[1],@Tx[2],30);
1054         &vpor   (@X[0],@X[0],@Tx[0]);           # "X[0]"<<<=1
1055          eval(shift(@insns));
1056          eval(shift(@insns));
1057          eval(shift(@insns));
1058          eval(shift(@insns));
1059
1060         &vpslld (@Tx[2],@Tx[2],2);
1061         &vpxor  (@X[0],@X[0],@Tx[1]);
1062          eval(shift(@insns));
1063          eval(shift(@insns));
1064          eval(shift(@insns));
1065          eval(shift(@insns));
1066
1067         &vpxor  (@X[0],@X[0],@Tx[2]);           # "X[0]"^=("X[0]">>96)<<<2
1068          eval(shift(@insns));
1069          eval(shift(@insns));
1070           &vmovdqa      ($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)")      if ($Xi%5==0);  # K_XX_XX
1071          eval(shift(@insns));
1072          eval(shift(@insns));
1073
1074
1075          foreach (@insns) { eval; }     # remaining instructions [if any]
1076
1077   $Xi++;        push(@X,shift(@X));     # "rotate" X[]
1078 }
1079
1080 sub Xupdate_avx_32_79()
1081 { use integer;
1082   my $body = shift;
1083   my @insns = (&$body,&$body,&$body,&$body);    # 32 to 44 instructions
1084   my ($a,$b,$c,$d,$e);
1085
1086         &vpalignr(@Tx[0],@X[-1&7],@X[-2&7],8);  # compose "X[-6]"
1087         &vpxor  (@X[0],@X[0],@X[-4&7]);         # "X[0]"="X[-32]"^"X[-16]"
1088          eval(shift(@insns));           # body_20_39
1089          eval(shift(@insns));
1090          eval(shift(@insns));
1091          eval(shift(@insns));           # rol
1092
1093         &vpxor  (@X[0],@X[0],@X[-7&7]);         # "X[0]"^="X[-28]"
1094          eval(shift(@insns));
1095          eval(shift(@insns))    if (@insns[0] !~ /&ro[rl]/);
1096           &vpaddd       (@Tx[1],$Kx,@X[-1&7]);
1097           &vmovdqa      ($Kx,eval(2*16*($Xi/5)-64)."($K_XX_XX)")        if ($Xi%5==0);
1098          eval(shift(@insns));           # ror
1099          eval(shift(@insns));
1100
1101         &vpxor  (@X[0],@X[0],@Tx[0]);           # "X[0]"^="X[-6]"
1102          eval(shift(@insns));           # body_20_39
1103          eval(shift(@insns));
1104          eval(shift(@insns));
1105          eval(shift(@insns));           # rol
1106
1107         &vpsrld (@Tx[0],@X[0],30);
1108           &vmovdqa      (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
1109          eval(shift(@insns));
1110          eval(shift(@insns));
1111          eval(shift(@insns));           # ror
1112          eval(shift(@insns));
1113
1114         &vpslld (@X[0],@X[0],2);
1115          eval(shift(@insns));           # body_20_39
1116          eval(shift(@insns));
1117          eval(shift(@insns));
1118          eval(shift(@insns));           # rol
1119          eval(shift(@insns));
1120          eval(shift(@insns));
1121          eval(shift(@insns));           # ror
1122          eval(shift(@insns));
1123
1124         &vpor   (@X[0],@X[0],@Tx[0]);           # "X[0]"<<<=2
1125          eval(shift(@insns));           # body_20_39
1126          eval(shift(@insns));
1127          eval(shift(@insns));
1128          eval(shift(@insns));           # rol
1129          eval(shift(@insns));
1130          eval(shift(@insns));
1131          eval(shift(@insns));           # rol
1132          eval(shift(@insns));
1133
1134          foreach (@insns) { eval; }     # remaining instructions
1135
1136   $Xi++;        push(@X,shift(@X));     # "rotate" X[]
1137 }
1138
1139 sub Xuplast_avx_80()
1140 { use integer;
1141   my $body = shift;
1142   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
1143   my ($a,$b,$c,$d,$e);
1144
1145          eval(shift(@insns));
1146           &vpaddd       (@Tx[1],$Kx,@X[-1&7]);
1147          eval(shift(@insns));
1148          eval(shift(@insns));
1149          eval(shift(@insns));
1150          eval(shift(@insns));
1151
1152           &vmovdqa      (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU
1153
1154          foreach (@insns) { eval; }             # remaining instructions
1155
1156         &cmp    ($inp,$num);
1157         &je     ($done_avx_label);
1158
1159         &vmovdqa(@X[2],"64($K_XX_XX)");         # pbswap mask
1160         &vmovdqa($Kx,"-64($K_XX_XX)");          # K_00_19
1161         &vmovdqu(@X[-4&7],"0($inp)");           # load input
1162         &vmovdqu(@X[-3&7],"16($inp)");
1163         &vmovdqu(@X[-2&7],"32($inp)");
1164         &vmovdqu(@X[-1&7],"48($inp)");
1165         &vpshufb(@X[-4&7],@X[-4&7],@X[2]);      # byte swap
1166         &add    ($inp,64);
1167
1168   $Xi=0;
1169 }
1170
1171 sub Xloop_avx()
1172 { use integer;
1173   my $body = shift;
1174   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
1175   my ($a,$b,$c,$d,$e);
1176
1177          eval(shift(@insns));
1178          eval(shift(@insns));
1179         &vpshufb(@X[($Xi-3)&7],@X[($Xi-3)&7],@X[2]);
1180          eval(shift(@insns));
1181          eval(shift(@insns));
1182         &vpaddd (@X[$Xi&7],@X[($Xi-4)&7],$Kx);
1183          eval(shift(@insns));
1184          eval(shift(@insns));
1185          eval(shift(@insns));
1186          eval(shift(@insns));
1187         &vmovdqa(eval(16*$Xi)."(%rsp)",@X[$Xi&7]);      # X[]+K xfer to IALU
1188          eval(shift(@insns));
1189          eval(shift(@insns));
1190
1191         foreach (@insns) { eval; }
1192   $Xi++;
1193 }
1194
1195 sub Xtail_avx()
1196 { use integer;
1197   my $body = shift;
1198   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
1199   my ($a,$b,$c,$d,$e);
1200
1201         foreach (@insns) { eval; }
1202 }
1203
1204 $code.=<<___;
1205 .align  16
1206 .Loop_avx:
1207 ___
1208         &Xupdate_avx_16_31(\&body_00_19);
1209         &Xupdate_avx_16_31(\&body_00_19);
1210         &Xupdate_avx_16_31(\&body_00_19);
1211         &Xupdate_avx_16_31(\&body_00_19);
1212         &Xupdate_avx_32_79(\&body_00_19);
1213         &Xupdate_avx_32_79(\&body_20_39);
1214         &Xupdate_avx_32_79(\&body_20_39);
1215         &Xupdate_avx_32_79(\&body_20_39);
1216         &Xupdate_avx_32_79(\&body_20_39);
1217         &Xupdate_avx_32_79(\&body_20_39);
1218         &Xupdate_avx_32_79(\&body_40_59);
1219         &Xupdate_avx_32_79(\&body_40_59);
1220         &Xupdate_avx_32_79(\&body_40_59);
1221         &Xupdate_avx_32_79(\&body_40_59);
1222         &Xupdate_avx_32_79(\&body_40_59);
1223         &Xupdate_avx_32_79(\&body_20_39);
1224         &Xuplast_avx_80(\&body_20_39);  # can jump to "done"
1225
1226                                 $saved_j=$j; @saved_V=@V;
1227
1228         &Xloop_avx(\&body_20_39);
1229         &Xloop_avx(\&body_20_39);
1230         &Xloop_avx(\&body_20_39);
1231
1232 $code.=<<___;
1233         add     0($ctx),$A                      # update context
1234         add     4($ctx),@T[0]
1235         add     8($ctx),$C
1236         add     12($ctx),$D
1237         mov     $A,0($ctx)
1238         add     16($ctx),$E
1239         mov     @T[0],4($ctx)
1240         mov     @T[0],$B                        # magic seed
1241         mov     $C,8($ctx)
1242         mov     $C,@T[1]
1243         mov     $D,12($ctx)
1244         xor     $D,@T[1]
1245         mov     $E,16($ctx)
1246         and     @T[1],@T[0]
1247         jmp     .Loop_avx
1248
1249 .align  16
1250 $done_avx_label:
1251 ___
1252                                 $j=$saved_j; @V=@saved_V;
1253
1254         &Xtail_avx(\&body_20_39);
1255         &Xtail_avx(\&body_20_39);
1256         &Xtail_avx(\&body_20_39);
1257
1258 $code.=<<___;
1259         vzeroupper
1260
1261         add     0($ctx),$A                      # update context
1262         add     4($ctx),@T[0]
1263         add     8($ctx),$C
1264         mov     $A,0($ctx)
1265         add     12($ctx),$D
1266         mov     @T[0],4($ctx)
1267         add     16($ctx),$E
1268         mov     $C,8($ctx)
1269         mov     $D,12($ctx)
1270         mov     $E,16($ctx)
1271 ___
1272 $code.=<<___ if ($win64);
1273         movaps  -40-6*16(%r14),%xmm6
1274         movaps  -40-5*16(%r14),%xmm7
1275         movaps  -40-4*16(%r14),%xmm8
1276         movaps  -40-3*16(%r14),%xmm9
1277         movaps  -40-2*16(%r14),%xmm10
1278         movaps  -40-1*16(%r14),%xmm11
1279 ___
1280 $code.=<<___;
1281         lea     (%r14),%rsi
1282         mov     -40(%rsi),%r14
1283         mov     -32(%rsi),%r13
1284         mov     -24(%rsi),%r12
1285         mov     -16(%rsi),%rbp
1286         mov     -8(%rsi),%rbx
1287         lea     (%rsi),%rsp
1288 .Lepilogue_avx:
1289         ret
1290 .size   sha1_block_data_order_avx,.-sha1_block_data_order_avx
1291 ___
1292
1293 if ($avx>1) {
1294 use integer;
1295 $Xi=4;                                  # reset variables
1296 @X=map("%ymm$_",(4..7,0..3));
1297 @Tx=map("%ymm$_",(8..10));
1298 $Kx="%ymm11";
1299 $j=0;
1300
1301 my @ROTX=("%eax","%ebp","%ebx","%ecx","%edx","%esi");
1302 my ($a5,$t0)=("%r12d","%edi");
1303
1304 my ($A,$F,$B,$C,$D,$E)=@ROTX;
1305 my $rx=0;
1306 my $frame="%r13";
1307
1308 $code.=<<___;
1309 .type   sha1_block_data_order_avx2,\@function,3
1310 .align  16
1311 sha1_block_data_order_avx2:
1312 _avx2_shortcut:
1313         mov     %rsp,%rax
1314         push    %rbx
1315         push    %rbp
1316         push    %r12
1317         push    %r13
1318         push    %r14
1319         vzeroupper
1320 ___
1321 $code.=<<___ if ($win64);
1322         lea     -6*16(%rsp),%rsp
1323         vmovaps %xmm6,-40-6*16(%rax)
1324         vmovaps %xmm7,-40-5*16(%rax)
1325         vmovaps %xmm8,-40-4*16(%rax)
1326         vmovaps %xmm9,-40-3*16(%rax)
1327         vmovaps %xmm10,-40-2*16(%rax)
1328         vmovaps %xmm11,-40-1*16(%rax)
1329 .Lprologue_avx2:
1330 ___
1331 $code.=<<___;
1332         mov     %rax,%r14               # original %rsp
1333         mov     %rdi,$ctx               # reassigned argument
1334         mov     %rsi,$inp               # reassigned argument
1335         mov     %rdx,$num               # reassigned argument
1336
1337         lea     -640(%rsp),%rsp
1338         shl     \$6,$num
1339          lea    64($inp),$frame
1340         and     \$-128,%rsp
1341         add     $inp,$num
1342         lea     K_XX_XX+64(%rip),$K_XX_XX
1343
1344         mov     0($ctx),$A              # load context
1345          cmp    $num,$frame
1346          cmovae $inp,$frame             # next or same block
1347         mov     4($ctx),$F
1348         mov     8($ctx),$C
1349         mov     12($ctx),$D
1350         mov     16($ctx),$E
1351         vmovdqu 64($K_XX_XX),@X[2]      # pbswap mask
1352
1353         vmovdqu         ($inp),%xmm0
1354         vmovdqu         16($inp),%xmm1
1355         vmovdqu         32($inp),%xmm2
1356         vmovdqu         48($inp),%xmm3
1357         lea             64($inp),$inp
1358         vinserti128     \$1,($frame),@X[-4&7],@X[-4&7]
1359         vinserti128     \$1,16($frame),@X[-3&7],@X[-3&7]
1360         vpshufb         @X[2],@X[-4&7],@X[-4&7]
1361         vinserti128     \$1,32($frame),@X[-2&7],@X[-2&7]
1362         vpshufb         @X[2],@X[-3&7],@X[-3&7]
1363         vinserti128     \$1,48($frame),@X[-1&7],@X[-1&7]
1364         vpshufb         @X[2],@X[-2&7],@X[-2&7]
1365         vmovdqu         -64($K_XX_XX),$Kx       # K_00_19
1366         vpshufb         @X[2],@X[-1&7],@X[-1&7]
1367
1368         vpaddd  $Kx,@X[-4&7],@X[0]      # add K_00_19
1369         vpaddd  $Kx,@X[-3&7],@X[1]
1370         vmovdqu @X[0],0(%rsp)           # X[]+K xfer to IALU
1371         vpaddd  $Kx,@X[-2&7],@X[2]
1372         vmovdqu @X[1],32(%rsp)
1373         vpaddd  $Kx,@X[-1&7],@X[3]
1374         vmovdqu @X[2],64(%rsp)
1375         vmovdqu @X[3],96(%rsp)
1376 ___
1377 for (;$Xi<8;$Xi++) {    # Xupdate_avx2_16_31
1378     use integer;
1379
1380         &vpalignr(@X[0],@X[-3&7],@X[-4&7],8);   # compose "X[-14]" in "X[0]"
1381         &vpsrldq(@Tx[0],@X[-1&7],4);            # "X[-3]", 3 dwords
1382         &vpxor  (@X[0],@X[0],@X[-4&7]);         # "X[0]"^="X[-16]"
1383         &vpxor  (@Tx[0],@Tx[0],@X[-2&7]);       # "X[-3]"^"X[-8]"
1384         &vpxor  (@X[0],@X[0],@Tx[0]);           # "X[0]"^="X[-3]"^"X[-8]"
1385         &vpsrld (@Tx[0],@X[0],31);
1386         &vmovdqu($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)")      if ($Xi%5==0);  # K_XX_XX
1387         &vpslldq(@Tx[2],@X[0],12);              # "X[0]"<<96, extract one dword
1388         &vpaddd (@X[0],@X[0],@X[0]);
1389         &vpsrld (@Tx[1],@Tx[2],30);
1390         &vpor   (@X[0],@X[0],@Tx[0]);           # "X[0]"<<<=1
1391         &vpslld (@Tx[2],@Tx[2],2);
1392         &vpxor  (@X[0],@X[0],@Tx[1]);
1393         &vpxor  (@X[0],@X[0],@Tx[2]);           # "X[0]"^=("X[0]">>96)<<<2
1394         &vpaddd (@Tx[1],@X[0],$Kx);
1395         &vmovdqu("32*$Xi(%rsp)",@Tx[1]);        # X[]+K xfer to IALU
1396
1397         push(@X,shift(@X));     # "rotate" X[]
1398 }
1399 $code.=<<___;
1400         lea     128(%rsp),$frame
1401         jmp     .Loop_avx2
1402 .align  32
1403 .Loop_avx2:
1404         rorx    \$2,$F,$B
1405         andn    $D,$F,$t0
1406         and     $C,$F
1407         xor     $t0,$F
1408 ___
1409 sub bodyx_00_19 () {    # 8 instructions, 3 cycles critical path
1410         # at start $f=(b&c)^(~b&d), $b>>>=2
1411         return &bodyx_20_39() if ($rx==19); $rx++;
1412         (
1413         '($a,$f,$b,$c,$d,$e)=@ROTX;'.
1414
1415         '&add   ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'.       # e+=X[i]+K
1416          '&lea  ($frame,"256($frame)")  if ($j%32==31);',
1417         '&andn  ($t0,$a,$c)',                   # ~b&d for next round
1418
1419         '&add   ($e,$f)',                       # e+=(b&c)^(~b&d)
1420         '&rorx  ($a5,$a,27)',                   # a<<<5
1421         '&rorx  ($f,$a,2)',                     # b>>>2 for next round
1422         '&and   ($a,$b)',                       # b&c for next round
1423
1424         '&add   ($e,$a5)',                      # e+=a<<<5
1425         '&xor   ($a,$t0);'.                     # f=(b&c)^(~b&d) for next round
1426
1427         'unshift(@ROTX,pop(@ROTX)); $j++;'
1428         )
1429 }
1430
1431 sub bodyx_20_39 () {    # 7 instructions, 2 cycles critical path
1432         # on entry $f=b^c^d, $b>>>=2
1433         return &bodyx_40_59() if ($rx==39); $rx++;
1434         (
1435         '($a,$f,$b,$c,$d,$e)=@ROTX;'.
1436
1437         '&add   ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'.       # e+=X[i]+K
1438          '&lea  ($frame,"256($frame)")  if ($j%32==31);',
1439
1440         '&lea   ($e,"($e,$f)")',                # e+=b^c^d
1441         '&rorx  ($a5,$a,27)',                   # a<<<5
1442         '&rorx  ($f,$a,2)       if ($j<79)',    # b>>>2 in next round
1443         '&xor   ($a,$b)         if ($j<79)',    # b^c for next round
1444
1445         '&add   ($e,$a5)',                      # e+=a<<<5
1446         '&xor   ($a,$c)         if ($j<79);'.   # f=b^c^d for next round
1447
1448         'unshift(@ROTX,pop(@ROTX)); $j++;'
1449         )
1450 }
1451
1452 sub bodyx_40_59 () {    # 10 instructions, 3 cycles critical path
1453         # on entry $f=((b^c)&(c^d)), $b>>>=2
1454         $rx++;
1455         (
1456         '($a,$f,$b,$c,$d,$e)=@ROTX;'.
1457
1458         '&add   ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'.       # e+=X[i]+K
1459          '&lea  ($frame,"256($frame)")  if ($j%32==31);',
1460         '&xor   ($f,$c)         if ($j>39)',    # (b^c)&(c^d)^c
1461         '&mov   ($t0,$b)        if ($j<59)',    # count on zero latency
1462         '&xor   ($t0,$c)        if ($j<59)',    # c^d for next round
1463
1464         '&lea   ($e,"($e,$f)")',                # e+=(b^c)&(c^d)^c
1465         '&rorx  ($a5,$a,27)',                   # a<<<5
1466         '&rorx  ($f,$a,2)',                     # b>>>2 in next round
1467         '&xor   ($a,$b)',                       # b^c for next round
1468
1469         '&add   ($e,$a5)',                      # e+=a<<<5
1470         '&and   ($a,$t0)        if ($j< 59);'.  # f=(b^c)&(c^d) for next round
1471         '&xor   ($a,$c)         if ($j==59);'.  # f=b^c^d for next round
1472
1473         'unshift(@ROTX,pop(@ROTX)); $j++;'
1474         )
1475 }
1476
1477 sub Xupdate_avx2_16_31()                # recall that $Xi starts wtih 4
1478 { use integer;
1479   my $body = shift;
1480   my @insns = (&$body,&$body,&$body,&$body,&$body);     # 35 instructions
1481   my ($a,$b,$c,$d,$e);
1482
1483         &vpalignr(@X[0],@X[-3&7],@X[-4&7],8);   # compose "X[-14]" in "X[0]"
1484          eval(shift(@insns));
1485          eval(shift(@insns));
1486          eval(shift(@insns));
1487          eval(shift(@insns));
1488
1489         &vpsrldq(@Tx[0],@X[-1&7],4);            # "X[-3]", 3 dwords
1490          eval(shift(@insns));
1491          eval(shift(@insns));
1492          eval(shift(@insns));
1493
1494         &vpxor  (@X[0],@X[0],@X[-4&7]);         # "X[0]"^="X[-16]"
1495         &vpxor  (@Tx[0],@Tx[0],@X[-2&7]);       # "X[-3]"^"X[-8]"
1496          eval(shift(@insns));
1497          eval(shift(@insns));
1498
1499         &vpxor  (@X[0],@X[0],@Tx[0]);           # "X[0]"^="X[-3]"^"X[-8]"
1500          eval(shift(@insns));
1501          eval(shift(@insns));
1502          eval(shift(@insns));
1503          eval(shift(@insns));
1504
1505         &vpsrld (@Tx[0],@X[0],31);
1506         &vmovdqu($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)")      if ($Xi%5==0);  # K_XX_XX
1507          eval(shift(@insns));
1508          eval(shift(@insns));
1509          eval(shift(@insns));
1510
1511         &vpslldq(@Tx[2],@X[0],12);              # "X[0]"<<96, extract one dword
1512         &vpaddd (@X[0],@X[0],@X[0]);
1513          eval(shift(@insns));
1514          eval(shift(@insns));
1515
1516         &vpsrld (@Tx[1],@Tx[2],30);
1517         &vpor   (@X[0],@X[0],@Tx[0]);           # "X[0]"<<<=1
1518          eval(shift(@insns));
1519          eval(shift(@insns));
1520
1521         &vpslld (@Tx[2],@Tx[2],2);
1522         &vpxor  (@X[0],@X[0],@Tx[1]);
1523          eval(shift(@insns));
1524          eval(shift(@insns));
1525
1526         &vpxor  (@X[0],@X[0],@Tx[2]);           # "X[0]"^=("X[0]">>96)<<<2
1527          eval(shift(@insns));
1528          eval(shift(@insns));
1529          eval(shift(@insns));
1530
1531         &vpaddd (@Tx[1],@X[0],$Kx);
1532          eval(shift(@insns));
1533          eval(shift(@insns));
1534          eval(shift(@insns));
1535         &vmovdqu(eval(32*($Xi))."(%rsp)",@Tx[1]);       # X[]+K xfer to IALU
1536
1537          foreach (@insns) { eval; }     # remaining instructions [if any]
1538
1539         $Xi++;
1540         push(@X,shift(@X));     # "rotate" X[]
1541 }
1542
1543 sub Xupdate_avx2_32_79()
1544 { use integer;
1545   my $body = shift;
1546   my @insns = (&$body,&$body,&$body,&$body,&$body);     # 35 to 50 instructions
1547   my ($a,$b,$c,$d,$e);
1548
1549         &vpalignr(@Tx[0],@X[-1&7],@X[-2&7],8);  # compose "X[-6]"
1550         &vpxor  (@X[0],@X[0],@X[-4&7]);         # "X[0]"="X[-32]"^"X[-16]"
1551          eval(shift(@insns));
1552          eval(shift(@insns));
1553
1554         &vpxor  (@X[0],@X[0],@X[-7&7]);         # "X[0]"^="X[-28]"
1555         &vmovdqu($Kx,eval(2*16*($Xi/5)-64)."($K_XX_XX)")        if ($Xi%5==0);
1556          eval(shift(@insns));
1557          eval(shift(@insns));
1558          eval(shift(@insns));
1559
1560         &vpxor  (@X[0],@X[0],@Tx[0]);           # "X[0]"^="X[-6]"
1561          eval(shift(@insns));
1562          eval(shift(@insns));
1563          eval(shift(@insns));
1564
1565         &vpsrld (@Tx[0],@X[0],30);
1566         &vpslld (@X[0],@X[0],2);
1567          eval(shift(@insns));
1568          eval(shift(@insns));
1569          eval(shift(@insns));
1570
1571         #&vpslld        (@X[0],@X[0],2);
1572          eval(shift(@insns));
1573          eval(shift(@insns));
1574          eval(shift(@insns));
1575
1576         &vpor   (@X[0],@X[0],@Tx[0]);           # "X[0]"<<<=2
1577          eval(shift(@insns));
1578          eval(shift(@insns));
1579          eval(shift(@insns));
1580          eval(shift(@insns));
1581
1582         &vpaddd (@Tx[1],@X[0],$Kx);
1583          eval(shift(@insns));
1584          eval(shift(@insns));
1585          eval(shift(@insns));
1586          eval(shift(@insns));
1587
1588         &vmovdqu("32*$Xi(%rsp)",@Tx[1]);        # X[]+K xfer to IALU
1589
1590          foreach (@insns) { eval; }     # remaining instructions
1591
1592         $Xi++;
1593         push(@X,shift(@X));     # "rotate" X[]
1594 }
1595
1596 sub Xloop_avx2()
1597 { use integer;
1598   my $body = shift;
1599   my @insns = (&$body,&$body,&$body,&$body,&$body);     # 32 instructions
1600   my ($a,$b,$c,$d,$e);
1601
1602          foreach (@insns) { eval; }
1603 }
1604
1605         &align32();
1606         &Xupdate_avx2_32_79(\&bodyx_00_19);
1607         &Xupdate_avx2_32_79(\&bodyx_00_19);
1608         &Xupdate_avx2_32_79(\&bodyx_00_19);
1609         &Xupdate_avx2_32_79(\&bodyx_00_19);
1610
1611         &Xupdate_avx2_32_79(\&bodyx_20_39);
1612         &Xupdate_avx2_32_79(\&bodyx_20_39);
1613         &Xupdate_avx2_32_79(\&bodyx_20_39);
1614         &Xupdate_avx2_32_79(\&bodyx_20_39);
1615
1616         &align32();
1617         &Xupdate_avx2_32_79(\&bodyx_40_59);
1618         &Xupdate_avx2_32_79(\&bodyx_40_59);
1619         &Xupdate_avx2_32_79(\&bodyx_40_59);
1620         &Xupdate_avx2_32_79(\&bodyx_40_59);
1621
1622         &Xloop_avx2(\&bodyx_20_39);
1623         &Xloop_avx2(\&bodyx_20_39);
1624         &Xloop_avx2(\&bodyx_20_39);
1625         &Xloop_avx2(\&bodyx_20_39);
1626
1627 $code.=<<___;
1628         lea     128($inp),$frame
1629         lea     128($inp),%rdi                  # borrow $t0
1630         cmp     $num,$frame
1631         cmovae  $inp,$frame                     # next or previous block
1632
1633         # output is d-e-[a]-f-b-c => A=d,F=e,C=f,D=b,E=c
1634         add     0($ctx),@ROTX[0]                # update context
1635         add     4($ctx),@ROTX[1]
1636         add     8($ctx),@ROTX[3]
1637         mov     @ROTX[0],0($ctx)
1638         add     12($ctx),@ROTX[4]
1639         mov     @ROTX[1],4($ctx)
1640          mov    @ROTX[0],$A                     # A=d
1641         add     16($ctx),@ROTX[5]
1642          mov    @ROTX[3],$a5
1643         mov     @ROTX[3],8($ctx)
1644          mov    @ROTX[4],$D                     # D=b
1645          #xchg  @ROTX[5],$F                     # F=c, C=f
1646         mov     @ROTX[4],12($ctx)
1647          mov    @ROTX[1],$F                     # F=e
1648         mov     @ROTX[5],16($ctx)
1649         #mov    $F,16($ctx)
1650          mov    @ROTX[5],$E                     # E=c
1651          mov    $a5,$C                          # C=f
1652          #xchg  $F,$E                           # E=c, F=e
1653
1654         cmp     $num,$inp
1655         je      .Ldone_avx2
1656 ___
1657
1658 $Xi=4;                          # reset variables
1659 @X=map("%ymm$_",(4..7,0..3));
1660
1661 $code.=<<___;
1662         vmovdqu 64($K_XX_XX),@X[2]              # pbswap mask
1663         cmp     $num,%rdi                       # borrowed $t0
1664         ja      .Last_avx2
1665
1666         vmovdqu         -64(%rdi),%xmm0         # low part of @X[-4&7]
1667         vmovdqu         -48(%rdi),%xmm1
1668         vmovdqu         -32(%rdi),%xmm2
1669         vmovdqu         -16(%rdi),%xmm3
1670         vinserti128     \$1,0($frame),@X[-4&7],@X[-4&7]
1671         vinserti128     \$1,16($frame),@X[-3&7],@X[-3&7]
1672         vinserti128     \$1,32($frame),@X[-2&7],@X[-2&7]
1673         vinserti128     \$1,48($frame),@X[-1&7],@X[-1&7]
1674         jmp     .Last_avx2
1675
1676 .align  32
1677 .Last_avx2:
1678         lea     128+16(%rsp),$frame
1679         rorx    \$2,$F,$B
1680         andn    $D,$F,$t0
1681         and     $C,$F
1682         xor     $t0,$F
1683         sub     \$-128,$inp
1684 ___
1685         $rx=$j=0;       @ROTX=($A,$F,$B,$C,$D,$E);
1686
1687         &Xloop_avx2     (\&bodyx_00_19);
1688         &Xloop_avx2     (\&bodyx_00_19);
1689         &Xloop_avx2     (\&bodyx_00_19);
1690         &Xloop_avx2     (\&bodyx_00_19);
1691
1692         &Xloop_avx2     (\&bodyx_20_39);
1693           &vmovdqu      ($Kx,"-64($K_XX_XX)");          # K_00_19
1694           &vpshufb      (@X[-4&7],@X[-4&7],@X[2]);      # byte swap
1695         &Xloop_avx2     (\&bodyx_20_39);
1696           &vpshufb      (@X[-3&7],@X[-3&7],@X[2]);
1697           &vpaddd       (@Tx[0],@X[-4&7],$Kx);          # add K_00_19
1698         &Xloop_avx2     (\&bodyx_20_39);
1699           &vmovdqu      ("0(%rsp)",@Tx[0]);
1700           &vpshufb      (@X[-2&7],@X[-2&7],@X[2]);
1701           &vpaddd       (@Tx[1],@X[-3&7],$Kx);
1702         &Xloop_avx2     (\&bodyx_20_39);
1703           &vmovdqu      ("32(%rsp)",@Tx[1]);
1704           &vpshufb      (@X[-1&7],@X[-1&7],@X[2]);
1705           &vpaddd       (@X[2],@X[-2&7],$Kx);
1706
1707         &Xloop_avx2     (\&bodyx_40_59);
1708         &align32        ();
1709           &vmovdqu      ("64(%rsp)",@X[2]);
1710           &vpaddd       (@X[3],@X[-1&7],$Kx);
1711         &Xloop_avx2     (\&bodyx_40_59);
1712           &vmovdqu      ("96(%rsp)",@X[3]);
1713         &Xloop_avx2     (\&bodyx_40_59);
1714         &Xupdate_avx2_16_31(\&bodyx_40_59);
1715
1716         &Xupdate_avx2_16_31(\&bodyx_20_39);
1717         &Xupdate_avx2_16_31(\&bodyx_20_39);
1718         &Xupdate_avx2_16_31(\&bodyx_20_39);
1719         &Xloop_avx2     (\&bodyx_20_39);
1720
1721 $code.=<<___;
1722         lea     128(%rsp),$frame
1723
1724         # output is d-e-[a]-f-b-c => A=d,F=e,C=f,D=b,E=c
1725         add     0($ctx),@ROTX[0]                # update context
1726         add     4($ctx),@ROTX[1]
1727         add     8($ctx),@ROTX[3]
1728         mov     @ROTX[0],0($ctx)
1729         add     12($ctx),@ROTX[4]
1730         mov     @ROTX[1],4($ctx)
1731          mov    @ROTX[0],$A                     # A=d
1732         add     16($ctx),@ROTX[5]
1733          mov    @ROTX[3],$a5
1734         mov     @ROTX[3],8($ctx)
1735          mov    @ROTX[4],$D                     # D=b
1736          #xchg  @ROTX[5],$F                     # F=c, C=f
1737         mov     @ROTX[4],12($ctx)
1738          mov    @ROTX[1],$F                     # F=e
1739         mov     @ROTX[5],16($ctx)
1740         #mov    $F,16($ctx)
1741          mov    @ROTX[5],$E                     # E=c
1742          mov    $a5,$C                          # C=f
1743          #xchg  $F,$E                           # E=c, F=e
1744
1745         cmp     $num,$inp
1746         jbe     .Loop_avx2
1747
1748 .Ldone_avx2:
1749         vzeroupper
1750 ___
1751 $code.=<<___ if ($win64);
1752         movaps  -40-6*16(%r14),%xmm6
1753         movaps  -40-5*16(%r14),%xmm7
1754         movaps  -40-4*16(%r14),%xmm8
1755         movaps  -40-3*16(%r14),%xmm9
1756         movaps  -40-2*16(%r14),%xmm10
1757         movaps  -40-1*16(%r14),%xmm11
1758 ___
1759 $code.=<<___;
1760         lea     (%r14),%rsi
1761         mov     -40(%rsi),%r14
1762         mov     -32(%rsi),%r13
1763         mov     -24(%rsi),%r12
1764         mov     -16(%rsi),%rbp
1765         mov     -8(%rsi),%rbx
1766         lea     (%rsi),%rsp
1767 .Lepilogue_avx2:
1768         ret
1769 .size   sha1_block_data_order_avx2,.-sha1_block_data_order_avx2
1770 ___
1771 }
1772 }
1773 $code.=<<___;
1774 .align  64
1775 K_XX_XX:
1776 .long   0x5a827999,0x5a827999,0x5a827999,0x5a827999     # K_00_19
1777 .long   0x5a827999,0x5a827999,0x5a827999,0x5a827999     # K_00_19
1778 .long   0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1     # K_20_39
1779 .long   0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1     # K_20_39
1780 .long   0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc     # K_40_59
1781 .long   0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc     # K_40_59
1782 .long   0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6     # K_60_79
1783 .long   0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6     # K_60_79
1784 .long   0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f     # pbswap mask
1785 .long   0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f     # pbswap mask
1786 .byte   0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0
1787 ___
1788 }}}
1789 $code.=<<___;
1790 .asciz  "SHA1 block transform for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
1791 .align  64
1792 ___
1793
1794 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
1795 #               CONTEXT *context,DISPATCHER_CONTEXT *disp)
1796 if ($win64) {
1797 $rec="%rcx";
1798 $frame="%rdx";
1799 $context="%r8";
1800 $disp="%r9";
1801
1802 $code.=<<___;
1803 .extern __imp_RtlVirtualUnwind
1804 .type   se_handler,\@abi-omnipotent
1805 .align  16
1806 se_handler:
1807         push    %rsi
1808         push    %rdi
1809         push    %rbx
1810         push    %rbp
1811         push    %r12
1812         push    %r13
1813         push    %r14
1814         push    %r15
1815         pushfq
1816         sub     \$64,%rsp
1817
1818         mov     120($context),%rax      # pull context->Rax
1819         mov     248($context),%rbx      # pull context->Rip
1820
1821         lea     .Lprologue(%rip),%r10
1822         cmp     %r10,%rbx               # context->Rip<.Lprologue
1823         jb      .Lcommon_seh_tail
1824
1825         mov     152($context),%rax      # pull context->Rsp
1826
1827         lea     .Lepilogue(%rip),%r10
1828         cmp     %r10,%rbx               # context->Rip>=.Lepilogue
1829         jae     .Lcommon_seh_tail
1830
1831         mov     `16*4`(%rax),%rax       # pull saved stack pointer
1832
1833         mov     -8(%rax),%rbx
1834         mov     -16(%rax),%rbp
1835         mov     -24(%rax),%r12
1836         mov     -32(%rax),%r13
1837         mov     -40(%rax),%r14
1838         mov     %rbx,144($context)      # restore context->Rbx
1839         mov     %rbp,160($context)      # restore context->Rbp
1840         mov     %r12,216($context)      # restore context->R12
1841         mov     %r13,224($context)      # restore context->R13
1842         mov     %r14,232($context)      # restore context->R14
1843
1844         jmp     .Lcommon_seh_tail
1845 .size   se_handler,.-se_handler
1846 ___
1847
1848 $code.=<<___ if ($shaext);
1849 .type   shaext_handler,\@abi-omnipotent
1850 .align  16
1851 shaext_handler:
1852         push    %rsi
1853         push    %rdi
1854         push    %rbx
1855         push    %rbp
1856         push    %r12
1857         push    %r13
1858         push    %r14
1859         push    %r15
1860         pushfq
1861         sub     \$64,%rsp
1862
1863         mov     120($context),%rax      # pull context->Rax
1864         mov     248($context),%rbx      # pull context->Rip
1865
1866         lea     .Lprologue_shaext(%rip),%r10
1867         cmp     %r10,%rbx               # context->Rip<.Lprologue
1868         jb      .Lcommon_seh_tail
1869
1870         lea     .Lepilogue_shaext(%rip),%r10
1871         cmp     %r10,%rbx               # context->Rip>=.Lepilogue
1872         jae     .Lcommon_seh_tail
1873
1874         lea     -8-4*16(%rax),%rsi
1875         lea     512($context),%rdi      # &context.Xmm6
1876         mov     \$8,%ecx
1877         .long   0xa548f3fc              # cld; rep movsq
1878
1879         jmp     .Lcommon_seh_tail
1880 .size   shaext_handler,.-shaext_handler
1881 ___
1882
1883 $code.=<<___;
1884 .type   ssse3_handler,\@abi-omnipotent
1885 .align  16
1886 ssse3_handler:
1887         push    %rsi
1888         push    %rdi
1889         push    %rbx
1890         push    %rbp
1891         push    %r12
1892         push    %r13
1893         push    %r14
1894         push    %r15
1895         pushfq
1896         sub     \$64,%rsp
1897
1898         mov     120($context),%rax      # pull context->Rax
1899         mov     248($context),%rbx      # pull context->Rip
1900
1901         mov     8($disp),%rsi           # disp->ImageBase
1902         mov     56($disp),%r11          # disp->HandlerData
1903
1904         mov     0(%r11),%r10d           # HandlerData[0]
1905         lea     (%rsi,%r10),%r10        # prologue label
1906         cmp     %r10,%rbx               # context->Rip<prologue label
1907         jb      .Lcommon_seh_tail
1908
1909         mov     152($context),%rax      # pull context->Rsp
1910
1911         mov     4(%r11),%r10d           # HandlerData[1]
1912         lea     (%rsi,%r10),%r10        # epilogue label
1913         cmp     %r10,%rbx               # context->Rip>=epilogue label
1914         jae     .Lcommon_seh_tail
1915
1916         mov     232($context),%rax      # pull context->R14
1917
1918         lea     -40-6*16(%rax),%rsi
1919         lea     512($context),%rdi      # &context.Xmm6
1920         mov     \$12,%ecx
1921         .long   0xa548f3fc              # cld; rep movsq
1922
1923         mov     -8(%rax),%rbx
1924         mov     -16(%rax),%rbp
1925         mov     -24(%rax),%r12
1926         mov     -32(%rax),%r13
1927         mov     -40(%rax),%r14
1928         mov     %rbx,144($context)      # restore context->Rbx
1929         mov     %rbp,160($context)      # restore context->Rbp
1930         mov     %r12,216($context)      # restore cotnext->R12
1931         mov     %r13,224($context)      # restore cotnext->R13
1932         mov     %r14,232($context)      # restore cotnext->R14
1933
1934 .Lcommon_seh_tail:
1935         mov     8(%rax),%rdi
1936         mov     16(%rax),%rsi
1937         mov     %rax,152($context)      # restore context->Rsp
1938         mov     %rsi,168($context)      # restore context->Rsi
1939         mov     %rdi,176($context)      # restore context->Rdi
1940
1941         mov     40($disp),%rdi          # disp->ContextRecord
1942         mov     $context,%rsi           # context
1943         mov     \$154,%ecx              # sizeof(CONTEXT)
1944         .long   0xa548f3fc              # cld; rep movsq
1945
1946         mov     $disp,%rsi
1947         xor     %rcx,%rcx               # arg1, UNW_FLAG_NHANDLER
1948         mov     8(%rsi),%rdx            # arg2, disp->ImageBase
1949         mov     0(%rsi),%r8             # arg3, disp->ControlPc
1950         mov     16(%rsi),%r9            # arg4, disp->FunctionEntry
1951         mov     40(%rsi),%r10           # disp->ContextRecord
1952         lea     56(%rsi),%r11           # &disp->HandlerData
1953         lea     24(%rsi),%r12           # &disp->EstablisherFrame
1954         mov     %r10,32(%rsp)           # arg5
1955         mov     %r11,40(%rsp)           # arg6
1956         mov     %r12,48(%rsp)           # arg7
1957         mov     %rcx,56(%rsp)           # arg8, (NULL)
1958         call    *__imp_RtlVirtualUnwind(%rip)
1959
1960         mov     \$1,%eax                # ExceptionContinueSearch
1961         add     \$64,%rsp
1962         popfq
1963         pop     %r15
1964         pop     %r14
1965         pop     %r13
1966         pop     %r12
1967         pop     %rbp
1968         pop     %rbx
1969         pop     %rdi
1970         pop     %rsi
1971         ret
1972 .size   ssse3_handler,.-ssse3_handler
1973
1974 .section        .pdata
1975 .align  4
1976         .rva    .LSEH_begin_sha1_block_data_order
1977         .rva    .LSEH_end_sha1_block_data_order
1978         .rva    .LSEH_info_sha1_block_data_order
1979 ___
1980 $code.=<<___ if ($shaext);
1981         .rva    .LSEH_begin_sha1_block_data_order_shaext
1982         .rva    .LSEH_end_sha1_block_data_order_shaext
1983         .rva    .LSEH_info_sha1_block_data_order_shaext
1984 ___
1985 $code.=<<___;
1986         .rva    .LSEH_begin_sha1_block_data_order_ssse3
1987         .rva    .LSEH_end_sha1_block_data_order_ssse3
1988         .rva    .LSEH_info_sha1_block_data_order_ssse3
1989 ___
1990 $code.=<<___ if ($avx);
1991         .rva    .LSEH_begin_sha1_block_data_order_avx
1992         .rva    .LSEH_end_sha1_block_data_order_avx
1993         .rva    .LSEH_info_sha1_block_data_order_avx
1994 ___
1995 $code.=<<___ if ($avx>1);
1996         .rva    .LSEH_begin_sha1_block_data_order_avx2
1997         .rva    .LSEH_end_sha1_block_data_order_avx2
1998         .rva    .LSEH_info_sha1_block_data_order_avx2
1999 ___
2000 $code.=<<___;
2001 .section        .xdata
2002 .align  8
2003 .LSEH_info_sha1_block_data_order:
2004         .byte   9,0,0,0
2005         .rva    se_handler
2006 ___
2007 $code.=<<___ if ($shaext);
2008 .LSEH_info_sha1_block_data_order_shaext:
2009         .byte   9,0,0,0
2010         .rva    shaext_handler
2011 ___
2012 $code.=<<___;
2013 .LSEH_info_sha1_block_data_order_ssse3:
2014         .byte   9,0,0,0
2015         .rva    ssse3_handler
2016         .rva    .Lprologue_ssse3,.Lepilogue_ssse3       # HandlerData[]
2017 ___
2018 $code.=<<___ if ($avx);
2019 .LSEH_info_sha1_block_data_order_avx:
2020         .byte   9,0,0,0
2021         .rva    ssse3_handler
2022         .rva    .Lprologue_avx,.Lepilogue_avx           # HandlerData[]
2023 ___
2024 $code.=<<___ if ($avx>1);
2025 .LSEH_info_sha1_block_data_order_avx2:
2026         .byte   9,0,0,0
2027         .rva    ssse3_handler
2028         .rva    .Lprologue_avx2,.Lepilogue_avx2         # HandlerData[]
2029 ___
2030 }
2031
2032 ####################################################################
2033
2034 sub sha1rnds4 {
2035     if (@_[0] =~ /\$([x0-9a-f]+),\s*%xmm([0-7]),\s*%xmm([0-7])/) {
2036       my @opcode=(0x0f,0x3a,0xcc);
2037         push @opcode,0xc0|($2&7)|(($3&7)<<3);           # ModR/M
2038         my $c=$1;
2039         push @opcode,$c=~/^0/?oct($c):$c;
2040         return ".byte\t".join(',',@opcode);
2041     } else {
2042         return "sha1rnds4\t".@_[0];
2043     }
2044 }
2045
2046 sub sha1op38 {
2047     my $instr = shift;
2048     my %opcodelet = (
2049                 "sha1nexte" => 0xc8,
2050                 "sha1msg1"  => 0xc9,
2051                 "sha1msg2"  => 0xca     );
2052
2053     if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) {
2054       my @opcode=(0x0f,0x38);
2055       my $rex=0;
2056         $rex|=0x04                      if ($2>=8);
2057         $rex|=0x01                      if ($1>=8);
2058         unshift @opcode,0x40|$rex       if ($rex);
2059         push @opcode,$opcodelet{$instr};
2060         push @opcode,0xc0|($1&7)|(($2&7)<<3);           # ModR/M
2061         return ".byte\t".join(',',@opcode);
2062     } else {
2063         return $instr."\t".@_[0];
2064     }
2065 }
2066
2067 foreach (split("\n",$code)) {
2068         s/\`([^\`]*)\`/eval $1/geo;
2069
2070         s/\b(sha1rnds4)\s+(.*)/sha1rnds4($2)/geo        or
2071         s/\b(sha1[^\s]*)\s+(.*)/sha1op38($1,$2)/geo;
2072
2073         print $_,"\n";
2074 }
2075 close STDOUT;