x86_64 assembly pack: Win64 SEH face-lift.
[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 # Goldmont      8.13            6.42/+27%       1.70/+380%(**)
89 #
90 # (*)   obviously suboptimal result, nothing was done about it,
91 #       because SSSE3 code is compiled unconditionally;
92 # (**)  SHAEXT result
93
94 $flavour = shift;
95 $output  = shift;
96 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
97
98 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
99
100 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
101 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
102 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
103 die "can't locate x86_64-xlate.pl";
104
105 if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
106                 =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
107         $avx = ($1>=2.19) + ($1>=2.22);
108 }
109
110 if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
111            `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
112         $avx = ($1>=2.09) + ($1>=2.10);
113 }
114
115 if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
116            `ml64 2>&1` =~ /Version ([0-9]+)\./) {
117         $avx = ($1>=10) + ($1>=11);
118 }
119
120 if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([2-9]\.[0-9]+)/) {
121         $avx = ($2>=3.0) + ($2>3.0);
122 }
123
124 $shaext=1;      ### set to zero if compiling for 1.0.1
125 $avx=1          if (!$shaext && $avx);
126
127 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
128 *STDOUT=*OUT;
129
130 $ctx="%rdi";    # 1st arg
131 $inp="%rsi";    # 2nd arg
132 $num="%rdx";    # 3rd arg
133
134 # reassign arguments in order to produce more compact code
135 $ctx="%r8";
136 $inp="%r9";
137 $num="%r10";
138
139 $t0="%eax";
140 $t1="%ebx";
141 $t2="%ecx";
142 @xi=("%edx","%ebp","%r14d");
143 $A="%esi";
144 $B="%edi";
145 $C="%r11d";
146 $D="%r12d";
147 $E="%r13d";
148
149 @V=($A,$B,$C,$D,$E);
150
151 sub BODY_00_19 {
152 my ($i,$a,$b,$c,$d,$e)=@_;
153 my $j=$i+1;
154 $code.=<<___ if ($i==0);
155         mov     `4*$i`($inp),$xi[0]
156         bswap   $xi[0]
157 ___
158 $code.=<<___ if ($i<15);
159         mov     `4*$j`($inp),$xi[1]
160         mov     $d,$t0
161         mov     $xi[0],`4*$i`(%rsp)
162         mov     $a,$t2
163         bswap   $xi[1]
164         xor     $c,$t0
165         rol     \$5,$t2
166         and     $b,$t0
167         lea     0x5a827999($xi[0],$e),$e
168         add     $t2,$e
169         xor     $d,$t0
170         rol     \$30,$b
171         add     $t0,$e
172 ___
173 $code.=<<___ if ($i>=15);
174         xor     `4*($j%16)`(%rsp),$xi[1]
175         mov     $d,$t0
176         mov     $xi[0],`4*($i%16)`(%rsp)
177         mov     $a,$t2
178         xor     `4*(($j+2)%16)`(%rsp),$xi[1]
179         xor     $c,$t0
180         rol     \$5,$t2
181         xor     `4*(($j+8)%16)`(%rsp),$xi[1]
182         and     $b,$t0
183         lea     0x5a827999($xi[0],$e),$e
184         rol     \$30,$b
185         xor     $d,$t0
186         add     $t2,$e
187         rol     \$1,$xi[1]
188         add     $t0,$e
189 ___
190 push(@xi,shift(@xi));
191 }
192
193 sub BODY_20_39 {
194 my ($i,$a,$b,$c,$d,$e)=@_;
195 my $j=$i+1;
196 my $K=($i<40)?0x6ed9eba1:0xca62c1d6;
197 $code.=<<___ if ($i<79);
198         xor     `4*($j%16)`(%rsp),$xi[1]
199         mov     $b,$t0
200         `"mov   $xi[0],".4*($i%16)."(%rsp)"     if ($i<72)`
201         mov     $a,$t2
202         xor     `4*(($j+2)%16)`(%rsp),$xi[1]
203         xor     $d,$t0
204         rol     \$5,$t2
205         xor     `4*(($j+8)%16)`(%rsp),$xi[1]
206         lea     $K($xi[0],$e),$e
207         xor     $c,$t0
208         add     $t2,$e
209         rol     \$30,$b
210         add     $t0,$e
211         rol     \$1,$xi[1]
212 ___
213 $code.=<<___ if ($i==79);
214         mov     $b,$t0
215         mov     $a,$t2
216         xor     $d,$t0
217         lea     $K($xi[0],$e),$e
218         rol     \$5,$t2
219         xor     $c,$t0
220         add     $t2,$e
221         rol     \$30,$b
222         add     $t0,$e
223 ___
224 push(@xi,shift(@xi));
225 }
226
227 sub BODY_40_59 {
228 my ($i,$a,$b,$c,$d,$e)=@_;
229 my $j=$i+1;
230 $code.=<<___;
231         xor     `4*($j%16)`(%rsp),$xi[1]
232         mov     $d,$t0
233         mov     $xi[0],`4*($i%16)`(%rsp)
234         mov     $d,$t1
235         xor     `4*(($j+2)%16)`(%rsp),$xi[1]
236         and     $c,$t0
237         mov     $a,$t2
238         xor     `4*(($j+8)%16)`(%rsp),$xi[1]
239         lea     0x8f1bbcdc($xi[0],$e),$e
240         xor     $c,$t1
241         rol     \$5,$t2
242         add     $t0,$e
243         rol     \$1,$xi[1]
244         and     $b,$t1
245         add     $t2,$e
246         rol     \$30,$b
247         add     $t1,$e
248 ___
249 push(@xi,shift(@xi));
250 }
251
252 $code.=<<___;
253 .text
254 .extern OPENSSL_ia32cap_P
255
256 .globl  sha1_block_data_order
257 .type   sha1_block_data_order,\@function,3
258 .align  16
259 sha1_block_data_order:
260         mov     OPENSSL_ia32cap_P+0(%rip),%r9d
261         mov     OPENSSL_ia32cap_P+4(%rip),%r8d
262         mov     OPENSSL_ia32cap_P+8(%rip),%r10d
263         test    \$`1<<9`,%r8d           # check SSSE3 bit
264         jz      .Lialu
265 ___
266 $code.=<<___ if ($shaext);
267         test    \$`1<<29`,%r10d         # check SHA bit
268         jnz     _shaext_shortcut
269 ___
270 $code.=<<___ if ($avx>1);
271         and     \$`1<<3|1<<5|1<<8`,%r10d        # check AVX2+BMI1+BMI2
272         cmp     \$`1<<3|1<<5|1<<8`,%r10d
273         je      _avx2_shortcut
274 ___
275 $code.=<<___ if ($avx);
276         and     \$`1<<28`,%r8d          # mask AVX bit
277         and     \$`1<<30`,%r9d          # mask "Intel CPU" bit
278         or      %r9d,%r8d
279         cmp     \$`1<<28|1<<30`,%r8d
280         je      _avx_shortcut
281 ___
282 $code.=<<___;
283         jmp     _ssse3_shortcut
284
285 .align  16
286 .Lialu:
287         mov     %rsp,%rax
288         push    %rbx
289         push    %rbp
290         push    %r12
291         push    %r13
292         push    %r14
293         mov     %rdi,$ctx       # reassigned argument
294         sub     \$`8+16*4`,%rsp
295         mov     %rsi,$inp       # reassigned argument
296         and     \$-64,%rsp
297         mov     %rdx,$num       # reassigned argument
298         mov     %rax,`16*4`(%rsp)
299 .Lprologue:
300
301         mov     0($ctx),$A
302         mov     4($ctx),$B
303         mov     8($ctx),$C
304         mov     12($ctx),$D
305         mov     16($ctx),$E
306         jmp     .Lloop
307
308 .align  16
309 .Lloop:
310 ___
311 for($i=0;$i<20;$i++)    { &BODY_00_19($i,@V); unshift(@V,pop(@V)); }
312 for(;$i<40;$i++)        { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
313 for(;$i<60;$i++)        { &BODY_40_59($i,@V); unshift(@V,pop(@V)); }
314 for(;$i<80;$i++)        { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
315 $code.=<<___;
316         add     0($ctx),$A
317         add     4($ctx),$B
318         add     8($ctx),$C
319         add     12($ctx),$D
320         add     16($ctx),$E
321         mov     $A,0($ctx)
322         mov     $B,4($ctx)
323         mov     $C,8($ctx)
324         mov     $D,12($ctx)
325         mov     $E,16($ctx)
326
327         sub     \$1,$num
328         lea     `16*4`($inp),$inp
329         jnz     .Lloop
330
331         mov     `16*4`(%rsp),%rsi
332         mov     -40(%rsi),%r14
333         mov     -32(%rsi),%r13
334         mov     -24(%rsi),%r12
335         mov     -16(%rsi),%rbp
336         mov     -8(%rsi),%rbx
337         lea     (%rsi),%rsp
338 .Lepilogue:
339         ret
340 .size   sha1_block_data_order,.-sha1_block_data_order
341 ___
342 if ($shaext) {{{
343 ######################################################################
344 # Intel SHA Extensions implementation of SHA1 update function.
345 #
346 my ($ctx,$inp,$num)=("%rdi","%rsi","%rdx");
347 my ($ABCD,$E,$E_,$BSWAP,$ABCD_SAVE,$E_SAVE)=map("%xmm$_",(0..3,8,9));
348 my @MSG=map("%xmm$_",(4..7));
349
350 $code.=<<___;
351 .type   sha1_block_data_order_shaext,\@function,3
352 .align  32
353 sha1_block_data_order_shaext:
354 _shaext_shortcut:
355 ___
356 $code.=<<___ if ($win64);
357         lea     `-8-4*16`(%rsp),%rsp
358         movaps  %xmm6,-8-4*16(%rax)
359         movaps  %xmm7,-8-3*16(%rax)
360         movaps  %xmm8,-8-2*16(%rax)
361         movaps  %xmm9,-8-1*16(%rax)
362 .Lprologue_shaext:
363 ___
364 $code.=<<___;
365         movdqu  ($ctx),$ABCD
366         movd    16($ctx),$E
367         movdqa  K_XX_XX+0xa0(%rip),$BSWAP       # byte-n-word swap
368
369         movdqu  ($inp),@MSG[0]
370         pshufd  \$0b00011011,$ABCD,$ABCD        # flip word order
371         movdqu  0x10($inp),@MSG[1]
372         pshufd  \$0b00011011,$E,$E              # flip word order
373         movdqu  0x20($inp),@MSG[2]
374         pshufb  $BSWAP,@MSG[0]
375         movdqu  0x30($inp),@MSG[3]
376         pshufb  $BSWAP,@MSG[1]
377         pshufb  $BSWAP,@MSG[2]
378         movdqa  $E,$E_SAVE                      # offload $E
379         pshufb  $BSWAP,@MSG[3]
380         jmp     .Loop_shaext
381
382 .align  16
383 .Loop_shaext:
384         dec             $num
385         lea             0x40($inp),%r8          # next input block
386         paddd           @MSG[0],$E
387         cmovne          %r8,$inp
388         movdqa          $ABCD,$ABCD_SAVE        # offload $ABCD
389 ___
390 for($i=0;$i<20-4;$i+=2) {
391 $code.=<<___;
392         sha1msg1        @MSG[1],@MSG[0]
393         movdqa          $ABCD,$E_
394         sha1rnds4       \$`int($i/5)`,$E,$ABCD  # 0-3...
395         sha1nexte       @MSG[1],$E_
396         pxor            @MSG[2],@MSG[0]
397         sha1msg1        @MSG[2],@MSG[1]
398         sha1msg2        @MSG[3],@MSG[0]
399
400         movdqa          $ABCD,$E
401         sha1rnds4       \$`int(($i+1)/5)`,$E_,$ABCD
402         sha1nexte       @MSG[2],$E
403         pxor            @MSG[3],@MSG[1]
404         sha1msg2        @MSG[0],@MSG[1]
405 ___
406         push(@MSG,shift(@MSG)); push(@MSG,shift(@MSG));
407 }
408 $code.=<<___;
409         movdqu          ($inp),@MSG[0]
410         movdqa          $ABCD,$E_
411         sha1rnds4       \$3,$E,$ABCD            # 64-67
412         sha1nexte       @MSG[1],$E_
413         movdqu          0x10($inp),@MSG[1]
414         pshufb          $BSWAP,@MSG[0]
415
416         movdqa          $ABCD,$E
417         sha1rnds4       \$3,$E_,$ABCD           # 68-71
418         sha1nexte       @MSG[2],$E
419         movdqu          0x20($inp),@MSG[2]
420         pshufb          $BSWAP,@MSG[1]
421
422         movdqa          $ABCD,$E_
423         sha1rnds4       \$3,$E,$ABCD            # 72-75
424         sha1nexte       @MSG[3],$E_
425         movdqu          0x30($inp),@MSG[3]
426         pshufb          $BSWAP,@MSG[2]
427
428         movdqa          $ABCD,$E
429         sha1rnds4       \$3,$E_,$ABCD           # 76-79
430         sha1nexte       $E_SAVE,$E
431         pshufb          $BSWAP,@MSG[3]
432
433         paddd           $ABCD_SAVE,$ABCD
434         movdqa          $E,$E_SAVE              # offload $E
435
436         jnz             .Loop_shaext
437
438         pshufd  \$0b00011011,$ABCD,$ABCD
439         pshufd  \$0b00011011,$E,$E
440         movdqu  $ABCD,($ctx)
441         movd    $E,16($ctx)
442 ___
443 $code.=<<___ if ($win64);
444         movaps  -8-4*16(%rax),%xmm6
445         movaps  -8-3*16(%rax),%xmm7
446         movaps  -8-2*16(%rax),%xmm8
447         movaps  -8-1*16(%rax),%xmm9
448         mov     %rax,%rsp
449 .Lepilogue_shaext:
450 ___
451 $code.=<<___;
452         ret
453 .size   sha1_block_data_order_shaext,.-sha1_block_data_order_shaext
454 ___
455 }}}
456 {{{
457 my $Xi=4;
458 my @X=map("%xmm$_",(4..7,0..3));
459 my @Tx=map("%xmm$_",(8..10));
460 my $Kx="%xmm11";
461 my @V=($A,$B,$C,$D,$E)=("%eax","%ebx","%ecx","%edx","%ebp");    # size optimization
462 my @T=("%esi","%edi");
463 my $j=0;
464 my $rx=0;
465 my $K_XX_XX="%r14";
466 my $fp="%r11";
467
468 my $_rol=sub { &rol(@_) };
469 my $_ror=sub { &ror(@_) };
470
471 { my $sn;
472 sub align32() {
473   ++$sn;
474 $code.=<<___;
475         jmp     .Lalign32_$sn   # see "Decoded ICache" in manual
476 .align  32
477 .Lalign32_$sn:
478 ___
479 }
480 }
481
482 $code.=<<___;
483 .type   sha1_block_data_order_ssse3,\@function,3
484 .align  16
485 sha1_block_data_order_ssse3:
486 _ssse3_shortcut:
487         mov     %rsp,$fp        # frame pointer
488         push    %rbx
489         push    %rbp
490         push    %r12
491         push    %r13            # redundant, done to share Win64 SE handler
492         push    %r14
493         lea     `-64-($win64?6*16:0)`(%rsp),%rsp
494 ___
495 $code.=<<___ if ($win64);
496         movaps  %xmm6,-40-6*16($fp)
497         movaps  %xmm7,-40-5*16($fp)
498         movaps  %xmm8,-40-4*16($fp)
499         movaps  %xmm9,-40-3*16($fp)
500         movaps  %xmm10,-40-2*16($fp)
501         movaps  %xmm11,-40-1*16($fp)
502 .Lprologue_ssse3:
503 ___
504 $code.=<<___;
505         and     \$-64,%rsp
506         mov     %rdi,$ctx       # reassigned argument
507         mov     %rsi,$inp       # reassigned argument
508         mov     %rdx,$num       # reassigned argument
509
510         shl     \$6,$num
511         add     $inp,$num
512         lea     K_XX_XX+64(%rip),$K_XX_XX
513
514         mov     0($ctx),$A              # load context
515         mov     4($ctx),$B
516         mov     8($ctx),$C
517         mov     12($ctx),$D
518         mov     $B,@T[0]                # magic seed
519         mov     16($ctx),$E
520         mov     $C,@T[1]
521         xor     $D,@T[1]
522         and     @T[1],@T[0]
523
524         movdqa  64($K_XX_XX),@X[2]      # pbswap mask
525         movdqa  -64($K_XX_XX),@Tx[1]    # K_00_19
526         movdqu  0($inp),@X[-4&7]        # load input to %xmm[0-3]
527         movdqu  16($inp),@X[-3&7]
528         movdqu  32($inp),@X[-2&7]
529         movdqu  48($inp),@X[-1&7]
530         pshufb  @X[2],@X[-4&7]          # byte swap
531         pshufb  @X[2],@X[-3&7]
532         pshufb  @X[2],@X[-2&7]
533         add     \$64,$inp
534         paddd   @Tx[1],@X[-4&7]         # add K_00_19
535         pshufb  @X[2],@X[-1&7]
536         paddd   @Tx[1],@X[-3&7]
537         paddd   @Tx[1],@X[-2&7]
538         movdqa  @X[-4&7],0(%rsp)        # X[]+K xfer to IALU
539         psubd   @Tx[1],@X[-4&7]         # restore X[]
540         movdqa  @X[-3&7],16(%rsp)
541         psubd   @Tx[1],@X[-3&7]
542         movdqa  @X[-2&7],32(%rsp)
543         psubd   @Tx[1],@X[-2&7]
544         jmp     .Loop_ssse3
545 ___
546
547 sub AUTOLOAD()          # thunk [simplified] 32-bit style perlasm
548 { my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
549   my $arg = pop;
550     $arg = "\$$arg" if ($arg*1 eq $arg);
551     $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
552 }
553
554 sub Xupdate_ssse3_16_31()               # recall that $Xi starts wtih 4
555 { use integer;
556   my $body = shift;
557   my @insns = (&$body,&$body,&$body,&$body);    # 40 instructions
558   my ($a,$b,$c,$d,$e);
559
560          eval(shift(@insns));           # ror
561         &pshufd (@X[0],@X[-4&7],0xee);  # was &movdqa   (@X[0],@X[-3&7]);
562          eval(shift(@insns));
563         &movdqa (@Tx[0],@X[-1&7]);
564           &paddd        (@Tx[1],@X[-1&7]);
565          eval(shift(@insns));
566          eval(shift(@insns));
567
568         &punpcklqdq(@X[0],@X[-3&7]);    # compose "X[-14]" in "X[0]", was &palignr(@X[0],@X[-4&7],8);
569          eval(shift(@insns));
570          eval(shift(@insns));           # rol
571          eval(shift(@insns));
572         &psrldq (@Tx[0],4);             # "X[-3]", 3 dwords
573          eval(shift(@insns));
574          eval(shift(@insns));
575
576         &pxor   (@X[0],@X[-4&7]);       # "X[0]"^="X[-16]"
577          eval(shift(@insns));
578          eval(shift(@insns));           # ror
579         &pxor   (@Tx[0],@X[-2&7]);      # "X[-3]"^"X[-8]"
580          eval(shift(@insns));
581          eval(shift(@insns));
582          eval(shift(@insns));
583
584         &pxor   (@X[0],@Tx[0]);         # "X[0]"^="X[-3]"^"X[-8]"
585          eval(shift(@insns));
586          eval(shift(@insns));           # rol
587           &movdqa       (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
588          eval(shift(@insns));
589          eval(shift(@insns));
590
591         &movdqa (@Tx[2],@X[0]);
592          eval(shift(@insns));
593          eval(shift(@insns));
594          eval(shift(@insns));           # ror
595         &movdqa (@Tx[0],@X[0]);
596          eval(shift(@insns));
597
598         &pslldq (@Tx[2],12);            # "X[0]"<<96, extract one dword
599         &paddd  (@X[0],@X[0]);
600          eval(shift(@insns));
601          eval(shift(@insns));
602
603         &psrld  (@Tx[0],31);
604          eval(shift(@insns));
605          eval(shift(@insns));           # rol
606          eval(shift(@insns));
607         &movdqa (@Tx[1],@Tx[2]);
608          eval(shift(@insns));
609          eval(shift(@insns));
610
611         &psrld  (@Tx[2],30);
612          eval(shift(@insns));
613          eval(shift(@insns));           # ror
614         &por    (@X[0],@Tx[0]);         # "X[0]"<<<=1
615          eval(shift(@insns));
616          eval(shift(@insns));
617          eval(shift(@insns));
618
619         &pslld  (@Tx[1],2);
620         &pxor   (@X[0],@Tx[2]);
621          eval(shift(@insns));
622           &movdqa       (@Tx[2],eval(2*16*(($Xi)/5)-64)."($K_XX_XX)");  # K_XX_XX
623          eval(shift(@insns));           # rol
624          eval(shift(@insns));
625          eval(shift(@insns));
626
627         &pxor   (@X[0],@Tx[1]);         # "X[0]"^=("X[0]">>96)<<<2
628         &pshufd (@Tx[1],@X[-1&7],0xee)  if ($Xi==7);    # was &movdqa   (@Tx[0],@X[-1&7]) in Xupdate_ssse3_32_79
629
630          foreach (@insns) { eval; }     # remaining instructions [if any]
631
632   $Xi++;        push(@X,shift(@X));     # "rotate" X[]
633                 push(@Tx,shift(@Tx));
634 }
635
636 sub Xupdate_ssse3_32_79()
637 { use integer;
638   my $body = shift;
639   my @insns = (&$body,&$body,&$body,&$body);    # 32 to 44 instructions
640   my ($a,$b,$c,$d,$e);
641
642          eval(shift(@insns))            if ($Xi==8);
643         &pxor   (@X[0],@X[-4&7]);       # "X[0]"="X[-32]"^"X[-16]"
644          eval(shift(@insns))            if ($Xi==8);
645          eval(shift(@insns));           # body_20_39
646          eval(shift(@insns));
647          eval(shift(@insns))            if (@insns[1] =~ /_ror/);
648          eval(shift(@insns))            if (@insns[0] =~ /_ror/);
649         &punpcklqdq(@Tx[0],@X[-1&7]);   # compose "X[-6]", was &palignr(@Tx[0],@X[-2&7],8);
650          eval(shift(@insns));
651          eval(shift(@insns));           # rol
652
653         &pxor   (@X[0],@X[-7&7]);       # "X[0]"^="X[-28]"
654          eval(shift(@insns));
655          eval(shift(@insns));
656         if ($Xi%5) {
657           &movdqa       (@Tx[2],@Tx[1]);# "perpetuate" K_XX_XX...
658         } else {                        # ... or load next one
659           &movdqa       (@Tx[2],eval(2*16*($Xi/5)-64)."($K_XX_XX)");
660         }
661          eval(shift(@insns));           # ror
662           &paddd        (@Tx[1],@X[-1&7]);
663          eval(shift(@insns));
664
665         &pxor   (@X[0],@Tx[0]);         # "X[0]"^="X[-6]"
666          eval(shift(@insns));           # body_20_39
667          eval(shift(@insns));
668          eval(shift(@insns));
669          eval(shift(@insns));           # rol
670          eval(shift(@insns))            if (@insns[0] =~ /_ror/);
671
672         &movdqa (@Tx[0],@X[0]);
673          eval(shift(@insns));
674          eval(shift(@insns));
675           &movdqa       (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
676          eval(shift(@insns));           # ror
677          eval(shift(@insns));
678          eval(shift(@insns));           # body_20_39
679
680         &pslld  (@X[0],2);
681          eval(shift(@insns));
682          eval(shift(@insns));
683         &psrld  (@Tx[0],30);
684          eval(shift(@insns))            if (@insns[0] =~ /_rol/);# rol
685          eval(shift(@insns));
686          eval(shift(@insns));
687          eval(shift(@insns));           # ror
688
689         &por    (@X[0],@Tx[0]);         # "X[0]"<<<=2
690          eval(shift(@insns));
691          eval(shift(@insns));           # body_20_39
692          eval(shift(@insns))            if (@insns[1] =~ /_rol/);
693          eval(shift(@insns))            if (@insns[0] =~ /_rol/);
694           &pshufd(@Tx[1],@X[-1&7],0xee) if ($Xi<19);    # was &movdqa   (@Tx[1],@X[0])
695          eval(shift(@insns));
696          eval(shift(@insns));           # rol
697          eval(shift(@insns));
698          eval(shift(@insns));
699          eval(shift(@insns));           # rol
700          eval(shift(@insns));
701
702          foreach (@insns) { eval; }     # remaining instructions
703
704   $Xi++;        push(@X,shift(@X));     # "rotate" X[]
705                 push(@Tx,shift(@Tx));
706 }
707
708 sub Xuplast_ssse3_80()
709 { use integer;
710   my $body = shift;
711   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
712   my ($a,$b,$c,$d,$e);
713
714          eval(shift(@insns));
715          eval(shift(@insns));
716          eval(shift(@insns));
717          eval(shift(@insns));
718           &paddd        (@Tx[1],@X[-1&7]);
719          eval(shift(@insns));
720          eval(shift(@insns));
721
722           &movdqa       (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU
723
724          foreach (@insns) { eval; }             # remaining instructions
725
726         &cmp    ($inp,$num);
727         &je     (".Ldone_ssse3");
728
729         unshift(@Tx,pop(@Tx));
730
731         &movdqa (@X[2],"64($K_XX_XX)");         # pbswap mask
732         &movdqa (@Tx[1],"-64($K_XX_XX)");       # K_00_19
733         &movdqu (@X[-4&7],"0($inp)");           # load input
734         &movdqu (@X[-3&7],"16($inp)");
735         &movdqu (@X[-2&7],"32($inp)");
736         &movdqu (@X[-1&7],"48($inp)");
737         &pshufb (@X[-4&7],@X[2]);               # byte swap
738         &add    ($inp,64);
739
740   $Xi=0;
741 }
742
743 sub Xloop_ssse3()
744 { use integer;
745   my $body = shift;
746   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
747   my ($a,$b,$c,$d,$e);
748
749          eval(shift(@insns));
750          eval(shift(@insns));
751          eval(shift(@insns));
752         &pshufb (@X[($Xi-3)&7],@X[2]);
753          eval(shift(@insns));
754          eval(shift(@insns));
755          eval(shift(@insns));
756          eval(shift(@insns));
757         &paddd  (@X[($Xi-4)&7],@Tx[1]);
758          eval(shift(@insns));
759          eval(shift(@insns));
760          eval(shift(@insns));
761          eval(shift(@insns));
762         &movdqa (eval(16*$Xi)."(%rsp)",@X[($Xi-4)&7]);  # X[]+K xfer to IALU
763          eval(shift(@insns));
764          eval(shift(@insns));
765          eval(shift(@insns));
766          eval(shift(@insns));
767         &psubd  (@X[($Xi-4)&7],@Tx[1]);
768
769         foreach (@insns) { eval; }
770   $Xi++;
771 }
772
773 sub Xtail_ssse3()
774 { use integer;
775   my $body = shift;
776   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
777   my ($a,$b,$c,$d,$e);
778
779         foreach (@insns) { eval; }
780 }
781
782 sub body_00_19 () {     # ((c^d)&b)^d
783         # on start @T[0]=(c^d)&b
784         return &body_20_39() if ($rx==19); $rx++;
785         (
786         '($a,$b,$c,$d,$e)=@V;'.
787         '&$_ror ($b,$j?7:2)',   # $b>>>2
788         '&xor   (@T[0],$d)',
789         '&mov   (@T[1],$a)',    # $b for next round
790
791         '&add   ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer
792         '&xor   ($b,$c)',       # $c^$d for next round
793
794         '&$_rol ($a,5)',
795         '&add   ($e,@T[0])',
796         '&and   (@T[1],$b)',    # ($b&($c^$d)) for next round
797
798         '&xor   ($b,$c)',       # restore $b
799         '&add   ($e,$a);'       .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
800         );
801 }
802
803 sub body_20_39 () {     # b^d^c
804         # on entry @T[0]=b^d
805         return &body_40_59() if ($rx==39); $rx++;
806         (
807         '($a,$b,$c,$d,$e)=@V;'.
808         '&add   ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer
809         '&xor   (@T[0],$d)      if($j==19);'.
810         '&xor   (@T[0],$c)      if($j> 19)',    # ($b^$d^$c)
811         '&mov   (@T[1],$a)',    # $b for next round
812
813         '&$_rol ($a,5)',
814         '&add   ($e,@T[0])',
815         '&xor   (@T[1],$c)      if ($j< 79)',   # $b^$d for next round
816
817         '&$_ror ($b,7)',        # $b>>>2
818         '&add   ($e,$a);'       .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
819         );
820 }
821
822 sub body_40_59 () {     # ((b^c)&(c^d))^c
823         # on entry @T[0]=(b^c), (c^=d)
824         $rx++;
825         (
826         '($a,$b,$c,$d,$e)=@V;'.
827         '&add   ($e,eval(4*($j&15))."(%rsp)")', # X[]+K xfer
828         '&and   (@T[0],$c)      if ($j>=40)',   # (b^c)&(c^d)
829         '&xor   ($c,$d)         if ($j>=40)',   # restore $c
830
831         '&$_ror ($b,7)',        # $b>>>2
832         '&mov   (@T[1],$a)',    # $b for next round
833         '&xor   (@T[0],$c)',
834
835         '&$_rol ($a,5)',
836         '&add   ($e,@T[0])',
837         '&xor   (@T[1],$c)      if ($j==59);'.
838         '&xor   (@T[1],$b)      if ($j< 59)',   # b^c for next round
839
840         '&xor   ($b,$c)         if ($j< 59)',   # c^d for next round
841         '&add   ($e,$a);'       .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
842         );
843 }
844 $code.=<<___;
845 .align  16
846 .Loop_ssse3:
847 ___
848         &Xupdate_ssse3_16_31(\&body_00_19);
849         &Xupdate_ssse3_16_31(\&body_00_19);
850         &Xupdate_ssse3_16_31(\&body_00_19);
851         &Xupdate_ssse3_16_31(\&body_00_19);
852         &Xupdate_ssse3_32_79(\&body_00_19);
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_20_39);
857         &Xupdate_ssse3_32_79(\&body_20_39);
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_40_59);
862         &Xupdate_ssse3_32_79(\&body_40_59);
863         &Xupdate_ssse3_32_79(\&body_20_39);
864         &Xuplast_ssse3_80(\&body_20_39);        # can jump to "done"
865
866                                 $saved_j=$j; @saved_V=@V;
867
868         &Xloop_ssse3(\&body_20_39);
869         &Xloop_ssse3(\&body_20_39);
870         &Xloop_ssse3(\&body_20_39);
871
872 $code.=<<___;
873         add     0($ctx),$A                      # update context
874         add     4($ctx),@T[0]
875         add     8($ctx),$C
876         add     12($ctx),$D
877         mov     $A,0($ctx)
878         add     16($ctx),$E
879         mov     @T[0],4($ctx)
880         mov     @T[0],$B                        # magic seed
881         mov     $C,8($ctx)
882         mov     $C,@T[1]
883         mov     $D,12($ctx)
884         xor     $D,@T[1]
885         mov     $E,16($ctx)
886         and     @T[1],@T[0]
887         jmp     .Loop_ssse3
888
889 .align  16
890 .Ldone_ssse3:
891 ___
892                                 $j=$saved_j; @V=@saved_V;
893
894         &Xtail_ssse3(\&body_20_39);
895         &Xtail_ssse3(\&body_20_39);
896         &Xtail_ssse3(\&body_20_39);
897
898 $code.=<<___;
899         add     0($ctx),$A                      # update context
900         add     4($ctx),@T[0]
901         add     8($ctx),$C
902         mov     $A,0($ctx)
903         add     12($ctx),$D
904         mov     @T[0],4($ctx)
905         add     16($ctx),$E
906         mov     $C,8($ctx)
907         mov     $D,12($ctx)
908         mov     $E,16($ctx)
909 ___
910 $code.=<<___ if ($win64);
911         movaps  -40-6*16($fp),%xmm6
912         movaps  -40-5*16($fp),%xmm7
913         movaps  -40-4*16($fp),%xmm8
914         movaps  -40-3*16($fp),%xmm9
915         movaps  -40-2*16($fp),%xmm10
916         movaps  -40-1*16($fp),%xmm11
917 ___
918 $code.=<<___;
919         mov     -40($fp),%r14
920         mov     -32($fp),%r13
921         mov     -24($fp),%r12
922         mov     -16($fp),%rbp
923         mov     -8($fp),%rbx
924         lea     ($fp),%rsp
925 .Lepilogue_ssse3:
926         ret
927 .size   sha1_block_data_order_ssse3,.-sha1_block_data_order_ssse3
928 ___
929
930 if ($avx) {
931 $Xi=4;                          # reset variables
932 @X=map("%xmm$_",(4..7,0..3));
933 @Tx=map("%xmm$_",(8..10));
934 $j=0;
935 $rx=0;
936
937 my $done_avx_label=".Ldone_avx";
938
939 my $_rol=sub { &shld(@_[0],@_) };
940 my $_ror=sub { &shrd(@_[0],@_) };
941
942 $code.=<<___;
943 .type   sha1_block_data_order_avx,\@function,3
944 .align  16
945 sha1_block_data_order_avx:
946 _avx_shortcut:
947         mov     %rsp,$fp
948         push    %rbx
949         push    %rbp
950         push    %r12
951         push    %r13            # redundant, done to share Win64 SE handler
952         push    %r14
953         lea     `-64-($win64?6*16:0)`(%rsp),%rsp
954         vzeroupper
955 ___
956 $code.=<<___ if ($win64);
957         vmovaps %xmm6,-40-6*16($fp)
958         vmovaps %xmm7,-40-5*16($fp)
959         vmovaps %xmm8,-40-4*16($fp)
960         vmovaps %xmm9,-40-3*16($fp)
961         vmovaps %xmm10,-40-2*16($fp)
962         vmovaps %xmm11,-40-1*16($fp)
963 .Lprologue_avx:
964 ___
965 $code.=<<___;
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($fp),%xmm6
1274         movaps  -40-5*16($fp),%xmm7
1275         movaps  -40-4*16($fp),%xmm8
1276         movaps  -40-3*16($fp),%xmm9
1277         movaps  -40-2*16($fp),%xmm10
1278         movaps  -40-1*16($fp),%xmm11
1279 ___
1280 $code.=<<___;
1281         mov     -40($fp),%r14
1282         mov     -32($fp),%r13
1283         mov     -24($fp),%r12
1284         mov     -16($fp),%rbp
1285         mov     -8($fp),%rbx
1286         lea     ($fp),%rsp
1287 .Lepilogue_avx:
1288         ret
1289 .size   sha1_block_data_order_avx,.-sha1_block_data_order_avx
1290 ___
1291
1292 if ($avx>1) {
1293 use integer;
1294 $Xi=4;                                  # reset variables
1295 @X=map("%ymm$_",(4..7,0..3));
1296 @Tx=map("%ymm$_",(8..10));
1297 $Kx="%ymm11";
1298 $j=0;
1299
1300 my @ROTX=("%eax","%ebp","%ebx","%ecx","%edx","%esi");
1301 my ($a5,$t0)=("%r12d","%edi");
1302
1303 my ($A,$F,$B,$C,$D,$E)=@ROTX;
1304 my $rx=0;
1305 my $frame="%r13";
1306
1307 $code.=<<___;
1308 .type   sha1_block_data_order_avx2,\@function,3
1309 .align  16
1310 sha1_block_data_order_avx2:
1311 _avx2_shortcut:
1312         mov     %rsp,$fp
1313         push    %rbx
1314         push    %rbp
1315         push    %r12
1316         push    %r13
1317         push    %r14
1318         vzeroupper
1319 ___
1320 $code.=<<___ if ($win64);
1321         lea     -6*16(%rsp),%rsp
1322         vmovaps %xmm6,-40-6*16($fp)
1323         vmovaps %xmm7,-40-5*16($fp)
1324         vmovaps %xmm8,-40-4*16($fp)
1325         vmovaps %xmm9,-40-3*16($fp)
1326         vmovaps %xmm10,-40-2*16($fp)
1327         vmovaps %xmm11,-40-1*16($fp)
1328 .Lprologue_avx2:
1329 ___
1330 $code.=<<___;
1331         mov     %rdi,$ctx               # reassigned argument
1332         mov     %rsi,$inp               # reassigned argument
1333         mov     %rdx,$num               # reassigned argument
1334
1335         lea     -640(%rsp),%rsp
1336         shl     \$6,$num
1337          lea    64($inp),$frame
1338         and     \$-128,%rsp
1339         add     $inp,$num
1340         lea     K_XX_XX+64(%rip),$K_XX_XX
1341
1342         mov     0($ctx),$A              # load context
1343          cmp    $num,$frame
1344          cmovae $inp,$frame             # next or same block
1345         mov     4($ctx),$F
1346         mov     8($ctx),$C
1347         mov     12($ctx),$D
1348         mov     16($ctx),$E
1349         vmovdqu 64($K_XX_XX),@X[2]      # pbswap mask
1350
1351         vmovdqu         ($inp),%xmm0
1352         vmovdqu         16($inp),%xmm1
1353         vmovdqu         32($inp),%xmm2
1354         vmovdqu         48($inp),%xmm3
1355         lea             64($inp),$inp
1356         vinserti128     \$1,($frame),@X[-4&7],@X[-4&7]
1357         vinserti128     \$1,16($frame),@X[-3&7],@X[-3&7]
1358         vpshufb         @X[2],@X[-4&7],@X[-4&7]
1359         vinserti128     \$1,32($frame),@X[-2&7],@X[-2&7]
1360         vpshufb         @X[2],@X[-3&7],@X[-3&7]
1361         vinserti128     \$1,48($frame),@X[-1&7],@X[-1&7]
1362         vpshufb         @X[2],@X[-2&7],@X[-2&7]
1363         vmovdqu         -64($K_XX_XX),$Kx       # K_00_19
1364         vpshufb         @X[2],@X[-1&7],@X[-1&7]
1365
1366         vpaddd  $Kx,@X[-4&7],@X[0]      # add K_00_19
1367         vpaddd  $Kx,@X[-3&7],@X[1]
1368         vmovdqu @X[0],0(%rsp)           # X[]+K xfer to IALU
1369         vpaddd  $Kx,@X[-2&7],@X[2]
1370         vmovdqu @X[1],32(%rsp)
1371         vpaddd  $Kx,@X[-1&7],@X[3]
1372         vmovdqu @X[2],64(%rsp)
1373         vmovdqu @X[3],96(%rsp)
1374 ___
1375 for (;$Xi<8;$Xi++) {    # Xupdate_avx2_16_31
1376     use integer;
1377
1378         &vpalignr(@X[0],@X[-3&7],@X[-4&7],8);   # compose "X[-14]" in "X[0]"
1379         &vpsrldq(@Tx[0],@X[-1&7],4);            # "X[-3]", 3 dwords
1380         &vpxor  (@X[0],@X[0],@X[-4&7]);         # "X[0]"^="X[-16]"
1381         &vpxor  (@Tx[0],@Tx[0],@X[-2&7]);       # "X[-3]"^"X[-8]"
1382         &vpxor  (@X[0],@X[0],@Tx[0]);           # "X[0]"^="X[-3]"^"X[-8]"
1383         &vpsrld (@Tx[0],@X[0],31);
1384         &vmovdqu($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)")      if ($Xi%5==0);  # K_XX_XX
1385         &vpslldq(@Tx[2],@X[0],12);              # "X[0]"<<96, extract one dword
1386         &vpaddd (@X[0],@X[0],@X[0]);
1387         &vpsrld (@Tx[1],@Tx[2],30);
1388         &vpor   (@X[0],@X[0],@Tx[0]);           # "X[0]"<<<=1
1389         &vpslld (@Tx[2],@Tx[2],2);
1390         &vpxor  (@X[0],@X[0],@Tx[1]);
1391         &vpxor  (@X[0],@X[0],@Tx[2]);           # "X[0]"^=("X[0]">>96)<<<2
1392         &vpaddd (@Tx[1],@X[0],$Kx);
1393         &vmovdqu("32*$Xi(%rsp)",@Tx[1]);        # X[]+K xfer to IALU
1394
1395         push(@X,shift(@X));     # "rotate" X[]
1396 }
1397 $code.=<<___;
1398         lea     128(%rsp),$frame
1399         jmp     .Loop_avx2
1400 .align  32
1401 .Loop_avx2:
1402         rorx    \$2,$F,$B
1403         andn    $D,$F,$t0
1404         and     $C,$F
1405         xor     $t0,$F
1406 ___
1407 sub bodyx_00_19 () {    # 8 instructions, 3 cycles critical path
1408         # at start $f=(b&c)^(~b&d), $b>>>=2
1409         return &bodyx_20_39() if ($rx==19); $rx++;
1410         (
1411         '($a,$f,$b,$c,$d,$e)=@ROTX;'.
1412
1413         '&add   ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'.       # e+=X[i]+K
1414          '&lea  ($frame,"256($frame)")  if ($j%32==31);',
1415         '&andn  ($t0,$a,$c)',                   # ~b&d for next round
1416
1417         '&add   ($e,$f)',                       # e+=(b&c)^(~b&d)
1418         '&rorx  ($a5,$a,27)',                   # a<<<5
1419         '&rorx  ($f,$a,2)',                     # b>>>2 for next round
1420         '&and   ($a,$b)',                       # b&c for next round
1421
1422         '&add   ($e,$a5)',                      # e+=a<<<5
1423         '&xor   ($a,$t0);'.                     # f=(b&c)^(~b&d) for next round
1424
1425         'unshift(@ROTX,pop(@ROTX)); $j++;'
1426         )
1427 }
1428
1429 sub bodyx_20_39 () {    # 7 instructions, 2 cycles critical path
1430         # on entry $f=b^c^d, $b>>>=2
1431         return &bodyx_40_59() if ($rx==39); $rx++;
1432         (
1433         '($a,$f,$b,$c,$d,$e)=@ROTX;'.
1434
1435         '&add   ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'.       # e+=X[i]+K
1436          '&lea  ($frame,"256($frame)")  if ($j%32==31);',
1437
1438         '&lea   ($e,"($e,$f)")',                # e+=b^c^d
1439         '&rorx  ($a5,$a,27)',                   # a<<<5
1440         '&rorx  ($f,$a,2)       if ($j<79)',    # b>>>2 in next round
1441         '&xor   ($a,$b)         if ($j<79)',    # b^c for next round
1442
1443         '&add   ($e,$a5)',                      # e+=a<<<5
1444         '&xor   ($a,$c)         if ($j<79);'.   # f=b^c^d for next round
1445
1446         'unshift(@ROTX,pop(@ROTX)); $j++;'
1447         )
1448 }
1449
1450 sub bodyx_40_59 () {    # 10 instructions, 3 cycles critical path
1451         # on entry $f=((b^c)&(c^d)), $b>>>=2
1452         $rx++;
1453         (
1454         '($a,$f,$b,$c,$d,$e)=@ROTX;'.
1455
1456         '&add   ($e,((32*($j/4)+4*($j%4))%256-128)."($frame)");'.       # e+=X[i]+K
1457          '&lea  ($frame,"256($frame)")  if ($j%32==31);',
1458         '&xor   ($f,$c)         if ($j>39)',    # (b^c)&(c^d)^c
1459         '&mov   ($t0,$b)        if ($j<59)',    # count on zero latency
1460         '&xor   ($t0,$c)        if ($j<59)',    # c^d for next round
1461
1462         '&lea   ($e,"($e,$f)")',                # e+=(b^c)&(c^d)^c
1463         '&rorx  ($a5,$a,27)',                   # a<<<5
1464         '&rorx  ($f,$a,2)',                     # b>>>2 in next round
1465         '&xor   ($a,$b)',                       # b^c for next round
1466
1467         '&add   ($e,$a5)',                      # e+=a<<<5
1468         '&and   ($a,$t0)        if ($j< 59);'.  # f=(b^c)&(c^d) for next round
1469         '&xor   ($a,$c)         if ($j==59);'.  # f=b^c^d for next round
1470
1471         'unshift(@ROTX,pop(@ROTX)); $j++;'
1472         )
1473 }
1474
1475 sub Xupdate_avx2_16_31()                # recall that $Xi starts wtih 4
1476 { use integer;
1477   my $body = shift;
1478   my @insns = (&$body,&$body,&$body,&$body,&$body);     # 35 instructions
1479   my ($a,$b,$c,$d,$e);
1480
1481         &vpalignr(@X[0],@X[-3&7],@X[-4&7],8);   # compose "X[-14]" in "X[0]"
1482          eval(shift(@insns));
1483          eval(shift(@insns));
1484          eval(shift(@insns));
1485          eval(shift(@insns));
1486
1487         &vpsrldq(@Tx[0],@X[-1&7],4);            # "X[-3]", 3 dwords
1488          eval(shift(@insns));
1489          eval(shift(@insns));
1490          eval(shift(@insns));
1491
1492         &vpxor  (@X[0],@X[0],@X[-4&7]);         # "X[0]"^="X[-16]"
1493         &vpxor  (@Tx[0],@Tx[0],@X[-2&7]);       # "X[-3]"^"X[-8]"
1494          eval(shift(@insns));
1495          eval(shift(@insns));
1496
1497         &vpxor  (@X[0],@X[0],@Tx[0]);           # "X[0]"^="X[-3]"^"X[-8]"
1498          eval(shift(@insns));
1499          eval(shift(@insns));
1500          eval(shift(@insns));
1501          eval(shift(@insns));
1502
1503         &vpsrld (@Tx[0],@X[0],31);
1504         &vmovdqu($Kx,eval(2*16*(($Xi)/5)-64)."($K_XX_XX)")      if ($Xi%5==0);  # K_XX_XX
1505          eval(shift(@insns));
1506          eval(shift(@insns));
1507          eval(shift(@insns));
1508
1509         &vpslldq(@Tx[2],@X[0],12);              # "X[0]"<<96, extract one dword
1510         &vpaddd (@X[0],@X[0],@X[0]);
1511          eval(shift(@insns));
1512          eval(shift(@insns));
1513
1514         &vpsrld (@Tx[1],@Tx[2],30);
1515         &vpor   (@X[0],@X[0],@Tx[0]);           # "X[0]"<<<=1
1516          eval(shift(@insns));
1517          eval(shift(@insns));
1518
1519         &vpslld (@Tx[2],@Tx[2],2);
1520         &vpxor  (@X[0],@X[0],@Tx[1]);
1521          eval(shift(@insns));
1522          eval(shift(@insns));
1523
1524         &vpxor  (@X[0],@X[0],@Tx[2]);           # "X[0]"^=("X[0]">>96)<<<2
1525          eval(shift(@insns));
1526          eval(shift(@insns));
1527          eval(shift(@insns));
1528
1529         &vpaddd (@Tx[1],@X[0],$Kx);
1530          eval(shift(@insns));
1531          eval(shift(@insns));
1532          eval(shift(@insns));
1533         &vmovdqu(eval(32*($Xi))."(%rsp)",@Tx[1]);       # X[]+K xfer to IALU
1534
1535          foreach (@insns) { eval; }     # remaining instructions [if any]
1536
1537         $Xi++;
1538         push(@X,shift(@X));     # "rotate" X[]
1539 }
1540
1541 sub Xupdate_avx2_32_79()
1542 { use integer;
1543   my $body = shift;
1544   my @insns = (&$body,&$body,&$body,&$body,&$body);     # 35 to 50 instructions
1545   my ($a,$b,$c,$d,$e);
1546
1547         &vpalignr(@Tx[0],@X[-1&7],@X[-2&7],8);  # compose "X[-6]"
1548         &vpxor  (@X[0],@X[0],@X[-4&7]);         # "X[0]"="X[-32]"^"X[-16]"
1549          eval(shift(@insns));
1550          eval(shift(@insns));
1551
1552         &vpxor  (@X[0],@X[0],@X[-7&7]);         # "X[0]"^="X[-28]"
1553         &vmovdqu($Kx,eval(2*16*($Xi/5)-64)."($K_XX_XX)")        if ($Xi%5==0);
1554          eval(shift(@insns));
1555          eval(shift(@insns));
1556          eval(shift(@insns));
1557
1558         &vpxor  (@X[0],@X[0],@Tx[0]);           # "X[0]"^="X[-6]"
1559          eval(shift(@insns));
1560          eval(shift(@insns));
1561          eval(shift(@insns));
1562
1563         &vpsrld (@Tx[0],@X[0],30);
1564         &vpslld (@X[0],@X[0],2);
1565          eval(shift(@insns));
1566          eval(shift(@insns));
1567          eval(shift(@insns));
1568
1569         #&vpslld        (@X[0],@X[0],2);
1570          eval(shift(@insns));
1571          eval(shift(@insns));
1572          eval(shift(@insns));
1573
1574         &vpor   (@X[0],@X[0],@Tx[0]);           # "X[0]"<<<=2
1575          eval(shift(@insns));
1576          eval(shift(@insns));
1577          eval(shift(@insns));
1578          eval(shift(@insns));
1579
1580         &vpaddd (@Tx[1],@X[0],$Kx);
1581          eval(shift(@insns));
1582          eval(shift(@insns));
1583          eval(shift(@insns));
1584          eval(shift(@insns));
1585
1586         &vmovdqu("32*$Xi(%rsp)",@Tx[1]);        # X[]+K xfer to IALU
1587
1588          foreach (@insns) { eval; }     # remaining instructions
1589
1590         $Xi++;
1591         push(@X,shift(@X));     # "rotate" X[]
1592 }
1593
1594 sub Xloop_avx2()
1595 { use integer;
1596   my $body = shift;
1597   my @insns = (&$body,&$body,&$body,&$body,&$body);     # 32 instructions
1598   my ($a,$b,$c,$d,$e);
1599
1600          foreach (@insns) { eval; }
1601 }
1602
1603         &align32();
1604         &Xupdate_avx2_32_79(\&bodyx_00_19);
1605         &Xupdate_avx2_32_79(\&bodyx_00_19);
1606         &Xupdate_avx2_32_79(\&bodyx_00_19);
1607         &Xupdate_avx2_32_79(\&bodyx_00_19);
1608
1609         &Xupdate_avx2_32_79(\&bodyx_20_39);
1610         &Xupdate_avx2_32_79(\&bodyx_20_39);
1611         &Xupdate_avx2_32_79(\&bodyx_20_39);
1612         &Xupdate_avx2_32_79(\&bodyx_20_39);
1613
1614         &align32();
1615         &Xupdate_avx2_32_79(\&bodyx_40_59);
1616         &Xupdate_avx2_32_79(\&bodyx_40_59);
1617         &Xupdate_avx2_32_79(\&bodyx_40_59);
1618         &Xupdate_avx2_32_79(\&bodyx_40_59);
1619
1620         &Xloop_avx2(\&bodyx_20_39);
1621         &Xloop_avx2(\&bodyx_20_39);
1622         &Xloop_avx2(\&bodyx_20_39);
1623         &Xloop_avx2(\&bodyx_20_39);
1624
1625 $code.=<<___;
1626         lea     128($inp),$frame
1627         lea     128($inp),%rdi                  # borrow $t0
1628         cmp     $num,$frame
1629         cmovae  $inp,$frame                     # next or previous block
1630
1631         # output is d-e-[a]-f-b-c => A=d,F=e,C=f,D=b,E=c
1632         add     0($ctx),@ROTX[0]                # update context
1633         add     4($ctx),@ROTX[1]
1634         add     8($ctx),@ROTX[3]
1635         mov     @ROTX[0],0($ctx)
1636         add     12($ctx),@ROTX[4]
1637         mov     @ROTX[1],4($ctx)
1638          mov    @ROTX[0],$A                     # A=d
1639         add     16($ctx),@ROTX[5]
1640          mov    @ROTX[3],$a5
1641         mov     @ROTX[3],8($ctx)
1642          mov    @ROTX[4],$D                     # D=b
1643          #xchg  @ROTX[5],$F                     # F=c, C=f
1644         mov     @ROTX[4],12($ctx)
1645          mov    @ROTX[1],$F                     # F=e
1646         mov     @ROTX[5],16($ctx)
1647         #mov    $F,16($ctx)
1648          mov    @ROTX[5],$E                     # E=c
1649          mov    $a5,$C                          # C=f
1650          #xchg  $F,$E                           # E=c, F=e
1651
1652         cmp     $num,$inp
1653         je      .Ldone_avx2
1654 ___
1655
1656 $Xi=4;                          # reset variables
1657 @X=map("%ymm$_",(4..7,0..3));
1658
1659 $code.=<<___;
1660         vmovdqu 64($K_XX_XX),@X[2]              # pbswap mask
1661         cmp     $num,%rdi                       # borrowed $t0
1662         ja      .Last_avx2
1663
1664         vmovdqu         -64(%rdi),%xmm0         # low part of @X[-4&7]
1665         vmovdqu         -48(%rdi),%xmm1
1666         vmovdqu         -32(%rdi),%xmm2
1667         vmovdqu         -16(%rdi),%xmm3
1668         vinserti128     \$1,0($frame),@X[-4&7],@X[-4&7]
1669         vinserti128     \$1,16($frame),@X[-3&7],@X[-3&7]
1670         vinserti128     \$1,32($frame),@X[-2&7],@X[-2&7]
1671         vinserti128     \$1,48($frame),@X[-1&7],@X[-1&7]
1672         jmp     .Last_avx2
1673
1674 .align  32
1675 .Last_avx2:
1676         lea     128+16(%rsp),$frame
1677         rorx    \$2,$F,$B
1678         andn    $D,$F,$t0
1679         and     $C,$F
1680         xor     $t0,$F
1681         sub     \$-128,$inp
1682 ___
1683         $rx=$j=0;       @ROTX=($A,$F,$B,$C,$D,$E);
1684
1685         &Xloop_avx2     (\&bodyx_00_19);
1686         &Xloop_avx2     (\&bodyx_00_19);
1687         &Xloop_avx2     (\&bodyx_00_19);
1688         &Xloop_avx2     (\&bodyx_00_19);
1689
1690         &Xloop_avx2     (\&bodyx_20_39);
1691           &vmovdqu      ($Kx,"-64($K_XX_XX)");          # K_00_19
1692           &vpshufb      (@X[-4&7],@X[-4&7],@X[2]);      # byte swap
1693         &Xloop_avx2     (\&bodyx_20_39);
1694           &vpshufb      (@X[-3&7],@X[-3&7],@X[2]);
1695           &vpaddd       (@Tx[0],@X[-4&7],$Kx);          # add K_00_19
1696         &Xloop_avx2     (\&bodyx_20_39);
1697           &vmovdqu      ("0(%rsp)",@Tx[0]);
1698           &vpshufb      (@X[-2&7],@X[-2&7],@X[2]);
1699           &vpaddd       (@Tx[1],@X[-3&7],$Kx);
1700         &Xloop_avx2     (\&bodyx_20_39);
1701           &vmovdqu      ("32(%rsp)",@Tx[1]);
1702           &vpshufb      (@X[-1&7],@X[-1&7],@X[2]);
1703           &vpaddd       (@X[2],@X[-2&7],$Kx);
1704
1705         &Xloop_avx2     (\&bodyx_40_59);
1706         &align32        ();
1707           &vmovdqu      ("64(%rsp)",@X[2]);
1708           &vpaddd       (@X[3],@X[-1&7],$Kx);
1709         &Xloop_avx2     (\&bodyx_40_59);
1710           &vmovdqu      ("96(%rsp)",@X[3]);
1711         &Xloop_avx2     (\&bodyx_40_59);
1712         &Xupdate_avx2_16_31(\&bodyx_40_59);
1713
1714         &Xupdate_avx2_16_31(\&bodyx_20_39);
1715         &Xupdate_avx2_16_31(\&bodyx_20_39);
1716         &Xupdate_avx2_16_31(\&bodyx_20_39);
1717         &Xloop_avx2     (\&bodyx_20_39);
1718
1719 $code.=<<___;
1720         lea     128(%rsp),$frame
1721
1722         # output is d-e-[a]-f-b-c => A=d,F=e,C=f,D=b,E=c
1723         add     0($ctx),@ROTX[0]                # update context
1724         add     4($ctx),@ROTX[1]
1725         add     8($ctx),@ROTX[3]
1726         mov     @ROTX[0],0($ctx)
1727         add     12($ctx),@ROTX[4]
1728         mov     @ROTX[1],4($ctx)
1729          mov    @ROTX[0],$A                     # A=d
1730         add     16($ctx),@ROTX[5]
1731          mov    @ROTX[3],$a5
1732         mov     @ROTX[3],8($ctx)
1733          mov    @ROTX[4],$D                     # D=b
1734          #xchg  @ROTX[5],$F                     # F=c, C=f
1735         mov     @ROTX[4],12($ctx)
1736          mov    @ROTX[1],$F                     # F=e
1737         mov     @ROTX[5],16($ctx)
1738         #mov    $F,16($ctx)
1739          mov    @ROTX[5],$E                     # E=c
1740          mov    $a5,$C                          # C=f
1741          #xchg  $F,$E                           # E=c, F=e
1742
1743         cmp     $num,$inp
1744         jbe     .Loop_avx2
1745
1746 .Ldone_avx2:
1747         vzeroupper
1748 ___
1749 $code.=<<___ if ($win64);
1750         movaps  -40-6*16($fp),%xmm6
1751         movaps  -40-5*16($fp),%xmm7
1752         movaps  -40-4*16($fp),%xmm8
1753         movaps  -40-3*16($fp),%xmm9
1754         movaps  -40-2*16($fp),%xmm10
1755         movaps  -40-1*16($fp),%xmm11
1756 ___
1757 $code.=<<___;
1758         mov     -40($fp),%r14
1759         mov     -32($fp),%r13
1760         mov     -24($fp),%r12
1761         mov     -16($fp),%rbp
1762         mov     -8($fp),%rbx
1763         lea     ($fp),%rsp
1764 .Lepilogue_avx2:
1765         ret
1766 .size   sha1_block_data_order_avx2,.-sha1_block_data_order_avx2
1767 ___
1768 }
1769 }
1770 $code.=<<___;
1771 .align  64
1772 K_XX_XX:
1773 .long   0x5a827999,0x5a827999,0x5a827999,0x5a827999     # K_00_19
1774 .long   0x5a827999,0x5a827999,0x5a827999,0x5a827999     # K_00_19
1775 .long   0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1     # K_20_39
1776 .long   0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1     # K_20_39
1777 .long   0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc     # K_40_59
1778 .long   0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc     # K_40_59
1779 .long   0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6     # K_60_79
1780 .long   0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6     # K_60_79
1781 .long   0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f     # pbswap mask
1782 .long   0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f     # pbswap mask
1783 .byte   0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0
1784 ___
1785 }}}
1786 $code.=<<___;
1787 .asciz  "SHA1 block transform for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
1788 .align  64
1789 ___
1790
1791 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
1792 #               CONTEXT *context,DISPATCHER_CONTEXT *disp)
1793 if ($win64) {
1794 $rec="%rcx";
1795 $frame="%rdx";
1796 $context="%r8";
1797 $disp="%r9";
1798
1799 $code.=<<___;
1800 .extern __imp_RtlVirtualUnwind
1801 .type   se_handler,\@abi-omnipotent
1802 .align  16
1803 se_handler:
1804         push    %rsi
1805         push    %rdi
1806         push    %rbx
1807         push    %rbp
1808         push    %r12
1809         push    %r13
1810         push    %r14
1811         push    %r15
1812         pushfq
1813         sub     \$64,%rsp
1814
1815         mov     120($context),%rax      # pull context->Rax
1816         mov     248($context),%rbx      # pull context->Rip
1817
1818         lea     .Lprologue(%rip),%r10
1819         cmp     %r10,%rbx               # context->Rip<.Lprologue
1820         jb      .Lcommon_seh_tail
1821
1822         mov     152($context),%rax      # pull context->Rsp
1823
1824         lea     .Lepilogue(%rip),%r10
1825         cmp     %r10,%rbx               # context->Rip>=.Lepilogue
1826         jae     .Lcommon_seh_tail
1827
1828         mov     `16*4`(%rax),%rax       # pull saved stack pointer
1829
1830         mov     -8(%rax),%rbx
1831         mov     -16(%rax),%rbp
1832         mov     -24(%rax),%r12
1833         mov     -32(%rax),%r13
1834         mov     -40(%rax),%r14
1835         mov     %rbx,144($context)      # restore context->Rbx
1836         mov     %rbp,160($context)      # restore context->Rbp
1837         mov     %r12,216($context)      # restore context->R12
1838         mov     %r13,224($context)      # restore context->R13
1839         mov     %r14,232($context)      # restore context->R14
1840
1841         jmp     .Lcommon_seh_tail
1842 .size   se_handler,.-se_handler
1843 ___
1844
1845 $code.=<<___ if ($shaext);
1846 .type   shaext_handler,\@abi-omnipotent
1847 .align  16
1848 shaext_handler:
1849         push    %rsi
1850         push    %rdi
1851         push    %rbx
1852         push    %rbp
1853         push    %r12
1854         push    %r13
1855         push    %r14
1856         push    %r15
1857         pushfq
1858         sub     \$64,%rsp
1859
1860         mov     120($context),%rax      # pull context->Rax
1861         mov     248($context),%rbx      # pull context->Rip
1862
1863         lea     .Lprologue_shaext(%rip),%r10
1864         cmp     %r10,%rbx               # context->Rip<.Lprologue
1865         jb      .Lcommon_seh_tail
1866
1867         lea     .Lepilogue_shaext(%rip),%r10
1868         cmp     %r10,%rbx               # context->Rip>=.Lepilogue
1869         jae     .Lcommon_seh_tail
1870
1871         lea     -8-4*16(%rax),%rsi
1872         lea     512($context),%rdi      # &context.Xmm6
1873         mov     \$8,%ecx
1874         .long   0xa548f3fc              # cld; rep movsq
1875
1876         jmp     .Lcommon_seh_tail
1877 .size   shaext_handler,.-shaext_handler
1878 ___
1879
1880 $code.=<<___;
1881 .type   ssse3_handler,\@abi-omnipotent
1882 .align  16
1883 ssse3_handler:
1884         push    %rsi
1885         push    %rdi
1886         push    %rbx
1887         push    %rbp
1888         push    %r12
1889         push    %r13
1890         push    %r14
1891         push    %r15
1892         pushfq
1893         sub     \$64,%rsp
1894
1895         mov     120($context),%rax      # pull context->Rax
1896         mov     248($context),%rbx      # pull context->Rip
1897
1898         mov     8($disp),%rsi           # disp->ImageBase
1899         mov     56($disp),%r11          # disp->HandlerData
1900
1901         mov     0(%r11),%r10d           # HandlerData[0]
1902         lea     (%rsi,%r10),%r10        # prologue label
1903         cmp     %r10,%rbx               # context->Rip<prologue label
1904         jb      .Lcommon_seh_tail
1905
1906         mov     208($context),%rax      # pull context->R11
1907
1908         mov     4(%r11),%r10d           # HandlerData[1]
1909         lea     (%rsi,%r10),%r10        # epilogue label
1910         cmp     %r10,%rbx               # context->Rip>=epilogue label
1911         jae     .Lcommon_seh_tail
1912
1913         lea     -40-6*16(%rax),%rsi
1914         lea     512($context),%rdi      # &context.Xmm6
1915         mov     \$12,%ecx
1916         .long   0xa548f3fc              # cld; rep movsq
1917
1918         mov     -8(%rax),%rbx
1919         mov     -16(%rax),%rbp
1920         mov     -24(%rax),%r12
1921         mov     -32(%rax),%r13
1922         mov     -40(%rax),%r14
1923         mov     %rbx,144($context)      # restore context->Rbx
1924         mov     %rbp,160($context)      # restore context->Rbp
1925         mov     %r12,216($context)      # restore cotnext->R12
1926         mov     %r13,224($context)      # restore cotnext->R13
1927         mov     %r14,232($context)      # restore cotnext->R14
1928
1929 .Lcommon_seh_tail:
1930         mov     8(%rax),%rdi
1931         mov     16(%rax),%rsi
1932         mov     %rax,152($context)      # restore context->Rsp
1933         mov     %rsi,168($context)      # restore context->Rsi
1934         mov     %rdi,176($context)      # restore context->Rdi
1935
1936         mov     40($disp),%rdi          # disp->ContextRecord
1937         mov     $context,%rsi           # context
1938         mov     \$154,%ecx              # sizeof(CONTEXT)
1939         .long   0xa548f3fc              # cld; rep movsq
1940
1941         mov     $disp,%rsi
1942         xor     %rcx,%rcx               # arg1, UNW_FLAG_NHANDLER
1943         mov     8(%rsi),%rdx            # arg2, disp->ImageBase
1944         mov     0(%rsi),%r8             # arg3, disp->ControlPc
1945         mov     16(%rsi),%r9            # arg4, disp->FunctionEntry
1946         mov     40(%rsi),%r10           # disp->ContextRecord
1947         lea     56(%rsi),%r11           # &disp->HandlerData
1948         lea     24(%rsi),%r12           # &disp->EstablisherFrame
1949         mov     %r10,32(%rsp)           # arg5
1950         mov     %r11,40(%rsp)           # arg6
1951         mov     %r12,48(%rsp)           # arg7
1952         mov     %rcx,56(%rsp)           # arg8, (NULL)
1953         call    *__imp_RtlVirtualUnwind(%rip)
1954
1955         mov     \$1,%eax                # ExceptionContinueSearch
1956         add     \$64,%rsp
1957         popfq
1958         pop     %r15
1959         pop     %r14
1960         pop     %r13
1961         pop     %r12
1962         pop     %rbp
1963         pop     %rbx
1964         pop     %rdi
1965         pop     %rsi
1966         ret
1967 .size   ssse3_handler,.-ssse3_handler
1968
1969 .section        .pdata
1970 .align  4
1971         .rva    .LSEH_begin_sha1_block_data_order
1972         .rva    .LSEH_end_sha1_block_data_order
1973         .rva    .LSEH_info_sha1_block_data_order
1974 ___
1975 $code.=<<___ if ($shaext);
1976         .rva    .LSEH_begin_sha1_block_data_order_shaext
1977         .rva    .LSEH_end_sha1_block_data_order_shaext
1978         .rva    .LSEH_info_sha1_block_data_order_shaext
1979 ___
1980 $code.=<<___;
1981         .rva    .LSEH_begin_sha1_block_data_order_ssse3
1982         .rva    .LSEH_end_sha1_block_data_order_ssse3
1983         .rva    .LSEH_info_sha1_block_data_order_ssse3
1984 ___
1985 $code.=<<___ if ($avx);
1986         .rva    .LSEH_begin_sha1_block_data_order_avx
1987         .rva    .LSEH_end_sha1_block_data_order_avx
1988         .rva    .LSEH_info_sha1_block_data_order_avx
1989 ___
1990 $code.=<<___ if ($avx>1);
1991         .rva    .LSEH_begin_sha1_block_data_order_avx2
1992         .rva    .LSEH_end_sha1_block_data_order_avx2
1993         .rva    .LSEH_info_sha1_block_data_order_avx2
1994 ___
1995 $code.=<<___;
1996 .section        .xdata
1997 .align  8
1998 .LSEH_info_sha1_block_data_order:
1999         .byte   9,0,0,0
2000         .rva    se_handler
2001 ___
2002 $code.=<<___ if ($shaext);
2003 .LSEH_info_sha1_block_data_order_shaext:
2004         .byte   9,0,0,0
2005         .rva    shaext_handler
2006 ___
2007 $code.=<<___;
2008 .LSEH_info_sha1_block_data_order_ssse3:
2009         .byte   9,0,0,0
2010         .rva    ssse3_handler
2011         .rva    .Lprologue_ssse3,.Lepilogue_ssse3       # HandlerData[]
2012 ___
2013 $code.=<<___ if ($avx);
2014 .LSEH_info_sha1_block_data_order_avx:
2015         .byte   9,0,0,0
2016         .rva    ssse3_handler
2017         .rva    .Lprologue_avx,.Lepilogue_avx           # HandlerData[]
2018 ___
2019 $code.=<<___ if ($avx>1);
2020 .LSEH_info_sha1_block_data_order_avx2:
2021         .byte   9,0,0,0
2022         .rva    ssse3_handler
2023         .rva    .Lprologue_avx2,.Lepilogue_avx2         # HandlerData[]
2024 ___
2025 }
2026
2027 ####################################################################
2028
2029 sub sha1rnds4 {
2030     if (@_[0] =~ /\$([x0-9a-f]+),\s*%xmm([0-7]),\s*%xmm([0-7])/) {
2031       my @opcode=(0x0f,0x3a,0xcc);
2032         push @opcode,0xc0|($2&7)|(($3&7)<<3);           # ModR/M
2033         my $c=$1;
2034         push @opcode,$c=~/^0/?oct($c):$c;
2035         return ".byte\t".join(',',@opcode);
2036     } else {
2037         return "sha1rnds4\t".@_[0];
2038     }
2039 }
2040
2041 sub sha1op38 {
2042     my $instr = shift;
2043     my %opcodelet = (
2044                 "sha1nexte" => 0xc8,
2045                 "sha1msg1"  => 0xc9,
2046                 "sha1msg2"  => 0xca     );
2047
2048     if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) {
2049       my @opcode=(0x0f,0x38);
2050       my $rex=0;
2051         $rex|=0x04                      if ($2>=8);
2052         $rex|=0x01                      if ($1>=8);
2053         unshift @opcode,0x40|$rex       if ($rex);
2054         push @opcode,$opcodelet{$instr};
2055         push @opcode,0xc0|($1&7)|(($2&7)<<3);           # ModR/M
2056         return ".byte\t".join(',',@opcode);
2057     } else {
2058         return $instr."\t".@_[0];
2059     }
2060 }
2061
2062 foreach (split("\n",$code)) {
2063         s/\`([^\`]*)\`/eval $1/geo;
2064
2065         s/\b(sha1rnds4)\s+(.*)/sha1rnds4($2)/geo        or
2066         s/\b(sha1[^\s]*)\s+(.*)/sha1op38($1,$2)/geo;
2067
2068         print $_,"\n";
2069 }
2070 close STDOUT;