bdf1d28fda29efb516f48bfee9bcd339b5befb76
[openssl.git] / crypto / sha / asm / sha512-x86_64.pl
1 #! /usr/bin/env perl
2 # Copyright 2005-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. Rights for redistribution and usage in source and binary
13 # forms are granted according to the OpenSSL license.
14 # ====================================================================
15 #
16 # sha256/512_block procedure for x86_64.
17 #
18 # 40% improvement over compiler-generated code on Opteron. On EM64T
19 # sha256 was observed to run >80% faster and sha512 - >40%. No magical
20 # tricks, just straight implementation... I really wonder why gcc
21 # [being armed with inline assembler] fails to generate as fast code.
22 # The only thing which is cool about this module is that it's very
23 # same instruction sequence used for both SHA-256 and SHA-512. In
24 # former case the instructions operate on 32-bit operands, while in
25 # latter - on 64-bit ones. All I had to do is to get one flavor right,
26 # the other one passed the test right away:-)
27 #
28 # sha256_block runs in ~1005 cycles on Opteron, which gives you
29 # asymptotic performance of 64*1000/1005=63.7MBps times CPU clock
30 # frequency in GHz. sha512_block runs in ~1275 cycles, which results
31 # in 128*1000/1275=100MBps per GHz. Is there room for improvement?
32 # Well, if you compare it to IA-64 implementation, which maintains
33 # X[16] in register bank[!], tends to 4 instructions per CPU clock
34 # cycle and runs in 1003 cycles, 1275 is very good result for 3-way
35 # issue Opteron pipeline and X[16] maintained in memory. So that *if*
36 # there is a way to improve it, *then* the only way would be to try to
37 # offload X[16] updates to SSE unit, but that would require "deeper"
38 # loop unroll, which in turn would naturally cause size blow-up, not
39 # to mention increased complexity! And once again, only *if* it's
40 # actually possible to noticeably improve overall ILP, instruction
41 # level parallelism, on a given CPU implementation in this case.
42 #
43 # Special note on Intel EM64T. While Opteron CPU exhibits perfect
44 # performance ratio of 1.5 between 64- and 32-bit flavors [see above],
45 # [currently available] EM64T CPUs apparently are far from it. On the
46 # contrary, 64-bit version, sha512_block, is ~30% *slower* than 32-bit
47 # sha256_block:-( This is presumably because 64-bit shifts/rotates
48 # apparently are not atomic instructions, but implemented in microcode.
49 #
50 # May 2012.
51 #
52 # Optimization including one of Pavel Semjanov's ideas, alternative
53 # Maj, resulted in >=5% improvement on most CPUs, +20% SHA256 and
54 # unfortunately -2% SHA512 on P4 [which nobody should care about
55 # that much].
56 #
57 # June 2012.
58 #
59 # Add SIMD code paths, see below for improvement coefficients. SSSE3
60 # code path was not attempted for SHA512, because improvement is not
61 # estimated to be high enough, noticeably less than 9%, to justify
62 # the effort, not on pre-AVX processors. [Obviously with exclusion
63 # for VIA Nano, but it has SHA512 instruction that is faster and
64 # should be used instead.] For reference, corresponding estimated
65 # upper limit for improvement for SSSE3 SHA256 is 28%. The fact that
66 # higher coefficients are observed on VIA Nano and Bulldozer has more
67 # to do with specifics of their architecture [which is topic for
68 # separate discussion].
69 #
70 # November 2012.
71 #
72 # Add AVX2 code path. Two consecutive input blocks are loaded to
73 # 256-bit %ymm registers, with data from first block to least
74 # significant 128-bit halves and data from second to most significant.
75 # The data is then processed with same SIMD instruction sequence as
76 # for AVX, but with %ymm as operands. Side effect is increased stack
77 # frame, 448 additional bytes in SHA256 and 1152 in SHA512, and 1.2KB
78 # code size increase.
79 #
80 # March 2014.
81 #
82 # Add support for Intel SHA Extensions.
83
84 ######################################################################
85 # Current performance in cycles per processed byte (less is better):
86 #
87 #               SHA256  SSSE3       AVX/XOP(*)      SHA512  AVX/XOP(*)
88 #
89 # AMD K8        14.9    -           -               9.57    -
90 # P4            17.3    -           -               30.8    -
91 # Core 2        15.6    13.8(+13%)  -               9.97    -
92 # Westmere      14.8    12.3(+19%)  -               9.58    -
93 # Sandy Bridge  17.4    14.2(+23%)  11.6(+50%(**))  11.2    8.10(+38%(**))
94 # Ivy Bridge    12.6    10.5(+20%)  10.3(+22%)      8.17    7.22(+13%)
95 # Haswell       12.2    9.28(+31%)  7.80(+56%)      7.66    5.40(+42%)
96 # Skylake       11.4    9.03(+26%)  7.70(+48%)      7.25    5.20(+40%)
97 # Bulldozer     21.1    13.6(+54%)  13.6(+54%(***)) 13.5    8.58(+57%)
98 # VIA Nano      23.0    16.5(+39%)  -               14.7    -
99 # Atom          23.0    18.9(+22%)  -               14.7    -
100 # Silvermont    27.4    20.6(+33%)  -               17.5    -
101 # Goldmont      18.9    14.3(+32%)  4.16(+350%)     12.0    -
102 #
103 # (*)   whichever best applicable, including SHAEXT;
104 # (**)  switch from ror to shrd stands for fair share of improvement;
105 # (***) execution time is fully determined by remaining integer-only
106 #       part, body_00_15; reducing the amount of SIMD instructions
107 #       below certain limit makes no difference/sense; to conserve
108 #       space SHA256 XOP code path is therefore omitted;
109
110 $flavour = shift;
111 $output  = shift;
112 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
113
114 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
115
116 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
117 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
118 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
119 die "can't locate x86_64-xlate.pl";
120
121 if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
122                 =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
123         $avx = ($1>=2.19) + ($1>=2.22);
124 }
125
126 if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
127            `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
128         $avx = ($1>=2.09) + ($1>=2.10);
129 }
130
131 if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
132            `ml64 2>&1` =~ /Version ([0-9]+)\./) {
133         $avx = ($1>=10) + ($1>=11);
134 }
135
136 if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) {
137         $avx = ($2>=3.0) + ($2>3.0);
138 }
139
140 $shaext=1;      ### set to zero if compiling for 1.0.1
141 $avx=1          if (!$shaext && $avx);
142
143 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
144 *STDOUT=*OUT;
145
146 if ($output =~ /512/) {
147         $func="sha512_block_data_order";
148         $TABLE="K512";
149         $SZ=8;
150         @ROT=($A,$B,$C,$D,$E,$F,$G,$H)=("%rax","%rbx","%rcx","%rdx",
151                                         "%r8", "%r9", "%r10","%r11");
152         ($T1,$a0,$a1,$a2,$a3)=("%r12","%r13","%r14","%r15","%rdi");
153         @Sigma0=(28,34,39);
154         @Sigma1=(14,18,41);
155         @sigma0=(1,  8, 7);
156         @sigma1=(19,61, 6);
157         $rounds=80;
158 } else {
159         $func="sha256_block_data_order";
160         $TABLE="K256";
161         $SZ=4;
162         @ROT=($A,$B,$C,$D,$E,$F,$G,$H)=("%eax","%ebx","%ecx","%edx",
163                                         "%r8d","%r9d","%r10d","%r11d");
164         ($T1,$a0,$a1,$a2,$a3)=("%r12d","%r13d","%r14d","%r15d","%edi");
165         @Sigma0=( 2,13,22);
166         @Sigma1=( 6,11,25);
167         @sigma0=( 7,18, 3);
168         @sigma1=(17,19,10);
169         $rounds=64;
170 }
171
172 $ctx="%rdi";    # 1st arg, zapped by $a3
173 $inp="%rsi";    # 2nd arg
174 $Tbl="%rbp";
175
176 $_ctx="16*$SZ+0*8(%rsp)";
177 $_inp="16*$SZ+1*8(%rsp)";
178 $_end="16*$SZ+2*8(%rsp)";
179 $_rsp="`16*$SZ+3*8`(%rsp)";
180 $framesz="16*$SZ+4*8";
181
182
183 sub ROUND_00_15()
184 { my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_;
185   my $STRIDE=$SZ;
186      $STRIDE += 16 if ($i%(16/$SZ)==(16/$SZ-1));
187
188 $code.=<<___;
189         ror     \$`$Sigma1[2]-$Sigma1[1]`,$a0
190         mov     $f,$a2
191
192         xor     $e,$a0
193         ror     \$`$Sigma0[2]-$Sigma0[1]`,$a1
194         xor     $g,$a2                  # f^g
195
196         mov     $T1,`$SZ*($i&0xf)`(%rsp)
197         xor     $a,$a1
198         and     $e,$a2                  # (f^g)&e
199
200         ror     \$`$Sigma1[1]-$Sigma1[0]`,$a0
201         add     $h,$T1                  # T1+=h
202         xor     $g,$a2                  # Ch(e,f,g)=((f^g)&e)^g
203
204         ror     \$`$Sigma0[1]-$Sigma0[0]`,$a1
205         xor     $e,$a0
206         add     $a2,$T1                 # T1+=Ch(e,f,g)
207
208         mov     $a,$a2
209         add     ($Tbl),$T1              # T1+=K[round]
210         xor     $a,$a1
211
212         xor     $b,$a2                  # a^b, b^c in next round
213         ror     \$$Sigma1[0],$a0        # Sigma1(e)
214         mov     $b,$h
215
216         and     $a2,$a3
217         ror     \$$Sigma0[0],$a1        # Sigma0(a)
218         add     $a0,$T1                 # T1+=Sigma1(e)
219
220         xor     $a3,$h                  # h=Maj(a,b,c)=Ch(a^b,c,b)
221         add     $T1,$d                  # d+=T1
222         add     $T1,$h                  # h+=T1
223
224         lea     $STRIDE($Tbl),$Tbl      # round++
225 ___
226 $code.=<<___ if ($i<15);
227         add     $a1,$h                  # h+=Sigma0(a)
228 ___
229         ($a2,$a3) = ($a3,$a2);
230 }
231
232 sub ROUND_16_XX()
233 { my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_;
234
235 $code.=<<___;
236         mov     `$SZ*(($i+1)&0xf)`(%rsp),$a0
237         mov     `$SZ*(($i+14)&0xf)`(%rsp),$a2
238
239         mov     $a0,$T1
240         ror     \$`$sigma0[1]-$sigma0[0]`,$a0
241         add     $a1,$a                  # modulo-scheduled h+=Sigma0(a)
242         mov     $a2,$a1
243         ror     \$`$sigma1[1]-$sigma1[0]`,$a2
244
245         xor     $T1,$a0
246         shr     \$$sigma0[2],$T1
247         ror     \$$sigma0[0],$a0
248         xor     $a1,$a2
249         shr     \$$sigma1[2],$a1
250
251         ror     \$$sigma1[0],$a2
252         xor     $a0,$T1                 # sigma0(X[(i+1)&0xf])
253         xor     $a1,$a2                 # sigma1(X[(i+14)&0xf])
254         add     `$SZ*(($i+9)&0xf)`(%rsp),$T1
255
256         add     `$SZ*($i&0xf)`(%rsp),$T1
257         mov     $e,$a0
258         add     $a2,$T1
259         mov     $a,$a1
260 ___
261         &ROUND_00_15(@_);
262 }
263
264 $code=<<___;
265 .text
266
267 .extern OPENSSL_ia32cap_P
268 .globl  $func
269 .type   $func,\@function,3
270 .align  16
271 $func:
272 .cfi_startproc
273 ___
274 $code.=<<___ if ($SZ==4 || $avx);
275         lea     OPENSSL_ia32cap_P(%rip),%r11
276         mov     0(%r11),%r9d
277         mov     4(%r11),%r10d
278         mov     8(%r11),%r11d
279 ___
280 $code.=<<___ if ($SZ==4 && $shaext);
281         test    \$`1<<29`,%r11d         # check for SHA
282         jnz     _shaext_shortcut
283 ___
284 $code.=<<___ if ($avx && $SZ==8);
285         test    \$`1<<11`,%r10d         # check for XOP
286         jnz     .Lxop_shortcut
287 ___
288 $code.=<<___ if ($avx>1);
289         and     \$`1<<8|1<<5|1<<3`,%r11d        # check for BMI2+AVX2+BMI1
290         cmp     \$`1<<8|1<<5|1<<3`,%r11d
291         je      .Lavx2_shortcut
292 ___
293 $code.=<<___ if ($avx);
294         and     \$`1<<30`,%r9d          # mask "Intel CPU" bit
295         and     \$`1<<28|1<<9`,%r10d    # mask AVX and SSSE3 bits
296         or      %r9d,%r10d
297         cmp     \$`1<<28|1<<9|1<<30`,%r10d
298         je      .Lavx_shortcut
299 ___
300 $code.=<<___ if ($SZ==4);
301         test    \$`1<<9`,%r10d
302         jnz     .Lssse3_shortcut
303 ___
304 $code.=<<___;
305         mov     %rsp,%rax               # copy %rsp
306 .cfi_def_cfa_register   %rax
307         push    %rbx
308 .cfi_push       %rbx
309         push    %rbp
310 .cfi_push       %rbp
311         push    %r12
312 .cfi_push       %r12
313         push    %r13
314 .cfi_push       %r13
315         push    %r14
316 .cfi_push       %r14
317         push    %r15
318 .cfi_push       %r15
319         shl     \$4,%rdx                # num*16
320         sub     \$$framesz,%rsp
321         lea     ($inp,%rdx,$SZ),%rdx    # inp+num*16*$SZ
322         and     \$-64,%rsp              # align stack frame
323         mov     $ctx,$_ctx              # save ctx, 1st arg
324         mov     $inp,$_inp              # save inp, 2nd arh
325         mov     %rdx,$_end              # save end pointer, "3rd" arg
326         mov     %rax,$_rsp              # save copy of %rsp
327 .cfi_cfa_expression     $_rsp,deref,+8
328 .Lprologue:
329
330         mov     $SZ*0($ctx),$A
331         mov     $SZ*1($ctx),$B
332         mov     $SZ*2($ctx),$C
333         mov     $SZ*3($ctx),$D
334         mov     $SZ*4($ctx),$E
335         mov     $SZ*5($ctx),$F
336         mov     $SZ*6($ctx),$G
337         mov     $SZ*7($ctx),$H
338         jmp     .Lloop
339
340 .align  16
341 .Lloop:
342         mov     $B,$a3
343         lea     $TABLE(%rip),$Tbl
344         xor     $C,$a3                  # magic
345 ___
346         for($i=0;$i<16;$i++) {
347                 $code.="        mov     $SZ*$i($inp),$T1\n";
348                 $code.="        mov     @ROT[4],$a0\n";
349                 $code.="        mov     @ROT[0],$a1\n";
350                 $code.="        bswap   $T1\n";
351                 &ROUND_00_15($i,@ROT);
352                 unshift(@ROT,pop(@ROT));
353         }
354 $code.=<<___;
355         jmp     .Lrounds_16_xx
356 .align  16
357 .Lrounds_16_xx:
358 ___
359         for(;$i<32;$i++) {
360                 &ROUND_16_XX($i,@ROT);
361                 unshift(@ROT,pop(@ROT));
362         }
363
364 $code.=<<___;
365         cmpb    \$0,`$SZ-1`($Tbl)
366         jnz     .Lrounds_16_xx
367
368         mov     $_ctx,$ctx
369         add     $a1,$A                  # modulo-scheduled h+=Sigma0(a)
370         lea     16*$SZ($inp),$inp
371
372         add     $SZ*0($ctx),$A
373         add     $SZ*1($ctx),$B
374         add     $SZ*2($ctx),$C
375         add     $SZ*3($ctx),$D
376         add     $SZ*4($ctx),$E
377         add     $SZ*5($ctx),$F
378         add     $SZ*6($ctx),$G
379         add     $SZ*7($ctx),$H
380
381         cmp     $_end,$inp
382
383         mov     $A,$SZ*0($ctx)
384         mov     $B,$SZ*1($ctx)
385         mov     $C,$SZ*2($ctx)
386         mov     $D,$SZ*3($ctx)
387         mov     $E,$SZ*4($ctx)
388         mov     $F,$SZ*5($ctx)
389         mov     $G,$SZ*6($ctx)
390         mov     $H,$SZ*7($ctx)
391         jb      .Lloop
392
393         mov     $_rsp,%rsi
394 .cfi_def_cfa    %rsi,8
395         mov     -48(%rsi),%r15
396 .cfi_restore    %r15
397         mov     -40(%rsi),%r14
398 .cfi_restore    %r14
399         mov     -32(%rsi),%r13
400 .cfi_restore    %r13
401         mov     -24(%rsi),%r12
402 .cfi_restore    %r12
403         mov     -16(%rsi),%rbp
404 .cfi_restore    %rbp
405         mov     -8(%rsi),%rbx
406 .cfi_restore    %rbx
407         lea     (%rsi),%rsp
408 .cfi_def_cfa_register   %rsp
409 .Lepilogue:
410         ret
411 .cfi_endproc
412 .size   $func,.-$func
413 ___
414
415 if ($SZ==4) {
416 $code.=<<___;
417 .align  64
418 .type   $TABLE,\@object
419 $TABLE:
420         .long   0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
421         .long   0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
422         .long   0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
423         .long   0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
424         .long   0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
425         .long   0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
426         .long   0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
427         .long   0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
428         .long   0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
429         .long   0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
430         .long   0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
431         .long   0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
432         .long   0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
433         .long   0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
434         .long   0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
435         .long   0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
436         .long   0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
437         .long   0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
438         .long   0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
439         .long   0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
440         .long   0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
441         .long   0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
442         .long   0xd192e819,0xd6990624,0xf40e3585,0x106aa070
443         .long   0xd192e819,0xd6990624,0xf40e3585,0x106aa070
444         .long   0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
445         .long   0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
446         .long   0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
447         .long   0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
448         .long   0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
449         .long   0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
450         .long   0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
451         .long   0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
452
453         .long   0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
454         .long   0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
455         .long   0x03020100,0x0b0a0908,0xffffffff,0xffffffff
456         .long   0x03020100,0x0b0a0908,0xffffffff,0xffffffff
457         .long   0xffffffff,0xffffffff,0x03020100,0x0b0a0908
458         .long   0xffffffff,0xffffffff,0x03020100,0x0b0a0908
459         .asciz  "SHA256 block transform for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
460 ___
461 } else {
462 $code.=<<___;
463 .align  64
464 .type   $TABLE,\@object
465 $TABLE:
466         .quad   0x428a2f98d728ae22,0x7137449123ef65cd
467         .quad   0x428a2f98d728ae22,0x7137449123ef65cd
468         .quad   0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
469         .quad   0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
470         .quad   0x3956c25bf348b538,0x59f111f1b605d019
471         .quad   0x3956c25bf348b538,0x59f111f1b605d019
472         .quad   0x923f82a4af194f9b,0xab1c5ed5da6d8118
473         .quad   0x923f82a4af194f9b,0xab1c5ed5da6d8118
474         .quad   0xd807aa98a3030242,0x12835b0145706fbe
475         .quad   0xd807aa98a3030242,0x12835b0145706fbe
476         .quad   0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
477         .quad   0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
478         .quad   0x72be5d74f27b896f,0x80deb1fe3b1696b1
479         .quad   0x72be5d74f27b896f,0x80deb1fe3b1696b1
480         .quad   0x9bdc06a725c71235,0xc19bf174cf692694
481         .quad   0x9bdc06a725c71235,0xc19bf174cf692694
482         .quad   0xe49b69c19ef14ad2,0xefbe4786384f25e3
483         .quad   0xe49b69c19ef14ad2,0xefbe4786384f25e3
484         .quad   0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
485         .quad   0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
486         .quad   0x2de92c6f592b0275,0x4a7484aa6ea6e483
487         .quad   0x2de92c6f592b0275,0x4a7484aa6ea6e483
488         .quad   0x5cb0a9dcbd41fbd4,0x76f988da831153b5
489         .quad   0x5cb0a9dcbd41fbd4,0x76f988da831153b5
490         .quad   0x983e5152ee66dfab,0xa831c66d2db43210
491         .quad   0x983e5152ee66dfab,0xa831c66d2db43210
492         .quad   0xb00327c898fb213f,0xbf597fc7beef0ee4
493         .quad   0xb00327c898fb213f,0xbf597fc7beef0ee4
494         .quad   0xc6e00bf33da88fc2,0xd5a79147930aa725
495         .quad   0xc6e00bf33da88fc2,0xd5a79147930aa725
496         .quad   0x06ca6351e003826f,0x142929670a0e6e70
497         .quad   0x06ca6351e003826f,0x142929670a0e6e70
498         .quad   0x27b70a8546d22ffc,0x2e1b21385c26c926
499         .quad   0x27b70a8546d22ffc,0x2e1b21385c26c926
500         .quad   0x4d2c6dfc5ac42aed,0x53380d139d95b3df
501         .quad   0x4d2c6dfc5ac42aed,0x53380d139d95b3df
502         .quad   0x650a73548baf63de,0x766a0abb3c77b2a8
503         .quad   0x650a73548baf63de,0x766a0abb3c77b2a8
504         .quad   0x81c2c92e47edaee6,0x92722c851482353b
505         .quad   0x81c2c92e47edaee6,0x92722c851482353b
506         .quad   0xa2bfe8a14cf10364,0xa81a664bbc423001
507         .quad   0xa2bfe8a14cf10364,0xa81a664bbc423001
508         .quad   0xc24b8b70d0f89791,0xc76c51a30654be30
509         .quad   0xc24b8b70d0f89791,0xc76c51a30654be30
510         .quad   0xd192e819d6ef5218,0xd69906245565a910
511         .quad   0xd192e819d6ef5218,0xd69906245565a910
512         .quad   0xf40e35855771202a,0x106aa07032bbd1b8
513         .quad   0xf40e35855771202a,0x106aa07032bbd1b8
514         .quad   0x19a4c116b8d2d0c8,0x1e376c085141ab53
515         .quad   0x19a4c116b8d2d0c8,0x1e376c085141ab53
516         .quad   0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
517         .quad   0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
518         .quad   0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
519         .quad   0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
520         .quad   0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
521         .quad   0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
522         .quad   0x748f82ee5defb2fc,0x78a5636f43172f60
523         .quad   0x748f82ee5defb2fc,0x78a5636f43172f60
524         .quad   0x84c87814a1f0ab72,0x8cc702081a6439ec
525         .quad   0x84c87814a1f0ab72,0x8cc702081a6439ec
526         .quad   0x90befffa23631e28,0xa4506cebde82bde9
527         .quad   0x90befffa23631e28,0xa4506cebde82bde9
528         .quad   0xbef9a3f7b2c67915,0xc67178f2e372532b
529         .quad   0xbef9a3f7b2c67915,0xc67178f2e372532b
530         .quad   0xca273eceea26619c,0xd186b8c721c0c207
531         .quad   0xca273eceea26619c,0xd186b8c721c0c207
532         .quad   0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
533         .quad   0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
534         .quad   0x06f067aa72176fba,0x0a637dc5a2c898a6
535         .quad   0x06f067aa72176fba,0x0a637dc5a2c898a6
536         .quad   0x113f9804bef90dae,0x1b710b35131c471b
537         .quad   0x113f9804bef90dae,0x1b710b35131c471b
538         .quad   0x28db77f523047d84,0x32caab7b40c72493
539         .quad   0x28db77f523047d84,0x32caab7b40c72493
540         .quad   0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
541         .quad   0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
542         .quad   0x4cc5d4becb3e42b6,0x597f299cfc657e2a
543         .quad   0x4cc5d4becb3e42b6,0x597f299cfc657e2a
544         .quad   0x5fcb6fab3ad6faec,0x6c44198c4a475817
545         .quad   0x5fcb6fab3ad6faec,0x6c44198c4a475817
546
547         .quad   0x0001020304050607,0x08090a0b0c0d0e0f
548         .quad   0x0001020304050607,0x08090a0b0c0d0e0f
549         .asciz  "SHA512 block transform for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
550 ___
551 }
552
553 ######################################################################
554 # SIMD code paths
555 #
556 if ($SZ==4 && $shaext) {{{
557 ######################################################################
558 # Intel SHA Extensions implementation of SHA256 update function.
559 #
560 my ($ctx,$inp,$num,$Tbl)=("%rdi","%rsi","%rdx","%rcx");
561
562 my ($Wi,$ABEF,$CDGH,$TMP,$BSWAP,$ABEF_SAVE,$CDGH_SAVE)=map("%xmm$_",(0..2,7..10));
563 my @MSG=map("%xmm$_",(3..6));
564
565 $code.=<<___;
566 .type   sha256_block_data_order_shaext,\@function,3
567 .align  64
568 sha256_block_data_order_shaext:
569 _shaext_shortcut:
570 ___
571 $code.=<<___ if ($win64);
572         lea     `-8-5*16`(%rsp),%rsp
573         movaps  %xmm6,-8-5*16(%rax)
574         movaps  %xmm7,-8-4*16(%rax)
575         movaps  %xmm8,-8-3*16(%rax)
576         movaps  %xmm9,-8-2*16(%rax)
577         movaps  %xmm10,-8-1*16(%rax)
578 .Lprologue_shaext:
579 ___
580 $code.=<<___;
581         lea             K256+0x80(%rip),$Tbl
582         movdqu          ($ctx),$ABEF            # DCBA
583         movdqu          16($ctx),$CDGH          # HGFE
584         movdqa          0x200-0x80($Tbl),$TMP   # byte swap mask
585
586         pshufd          \$0x1b,$ABEF,$Wi        # ABCD
587         pshufd          \$0xb1,$ABEF,$ABEF      # CDAB
588         pshufd          \$0x1b,$CDGH,$CDGH      # EFGH
589         movdqa          $TMP,$BSWAP             # offload
590         palignr         \$8,$CDGH,$ABEF         # ABEF
591         punpcklqdq      $Wi,$CDGH               # CDGH
592         jmp             .Loop_shaext
593
594 .align  16
595 .Loop_shaext:
596         movdqu          ($inp),@MSG[0]
597         movdqu          0x10($inp),@MSG[1]
598         movdqu          0x20($inp),@MSG[2]
599         pshufb          $TMP,@MSG[0]
600         movdqu          0x30($inp),@MSG[3]
601
602         movdqa          0*32-0x80($Tbl),$Wi
603         paddd           @MSG[0],$Wi
604         pshufb          $TMP,@MSG[1]
605         movdqa          $CDGH,$CDGH_SAVE        # offload
606         sha256rnds2     $ABEF,$CDGH             # 0-3
607         pshufd          \$0x0e,$Wi,$Wi
608         nop
609         movdqa          $ABEF,$ABEF_SAVE        # offload
610         sha256rnds2     $CDGH,$ABEF
611
612         movdqa          1*32-0x80($Tbl),$Wi
613         paddd           @MSG[1],$Wi
614         pshufb          $TMP,@MSG[2]
615         sha256rnds2     $ABEF,$CDGH             # 4-7
616         pshufd          \$0x0e,$Wi,$Wi
617         lea             0x40($inp),$inp
618         sha256msg1      @MSG[1],@MSG[0]
619         sha256rnds2     $CDGH,$ABEF
620
621         movdqa          2*32-0x80($Tbl),$Wi
622         paddd           @MSG[2],$Wi
623         pshufb          $TMP,@MSG[3]
624         sha256rnds2     $ABEF,$CDGH             # 8-11
625         pshufd          \$0x0e,$Wi,$Wi
626         movdqa          @MSG[3],$TMP
627         palignr         \$4,@MSG[2],$TMP
628         nop
629         paddd           $TMP,@MSG[0]
630         sha256msg1      @MSG[2],@MSG[1]
631         sha256rnds2     $CDGH,$ABEF
632
633         movdqa          3*32-0x80($Tbl),$Wi
634         paddd           @MSG[3],$Wi
635         sha256msg2      @MSG[3],@MSG[0]
636         sha256rnds2     $ABEF,$CDGH             # 12-15
637         pshufd          \$0x0e,$Wi,$Wi
638         movdqa          @MSG[0],$TMP
639         palignr         \$4,@MSG[3],$TMP
640         nop
641         paddd           $TMP,@MSG[1]
642         sha256msg1      @MSG[3],@MSG[2]
643         sha256rnds2     $CDGH,$ABEF
644 ___
645 for($i=4;$i<16-3;$i++) {
646 $code.=<<___;
647         movdqa          $i*32-0x80($Tbl),$Wi
648         paddd           @MSG[0],$Wi
649         sha256msg2      @MSG[0],@MSG[1]
650         sha256rnds2     $ABEF,$CDGH             # 16-19...
651         pshufd          \$0x0e,$Wi,$Wi
652         movdqa          @MSG[1],$TMP
653         palignr         \$4,@MSG[0],$TMP
654         nop
655         paddd           $TMP,@MSG[2]
656         sha256msg1      @MSG[0],@MSG[3]
657         sha256rnds2     $CDGH,$ABEF
658 ___
659         push(@MSG,shift(@MSG));
660 }
661 $code.=<<___;
662         movdqa          13*32-0x80($Tbl),$Wi
663         paddd           @MSG[0],$Wi
664         sha256msg2      @MSG[0],@MSG[1]
665         sha256rnds2     $ABEF,$CDGH             # 52-55
666         pshufd          \$0x0e,$Wi,$Wi
667         movdqa          @MSG[1],$TMP
668         palignr         \$4,@MSG[0],$TMP
669         sha256rnds2     $CDGH,$ABEF
670         paddd           $TMP,@MSG[2]
671
672         movdqa          14*32-0x80($Tbl),$Wi
673         paddd           @MSG[1],$Wi
674         sha256rnds2     $ABEF,$CDGH             # 56-59
675         pshufd          \$0x0e,$Wi,$Wi
676         sha256msg2      @MSG[1],@MSG[2]
677         movdqa          $BSWAP,$TMP
678         sha256rnds2     $CDGH,$ABEF
679
680         movdqa          15*32-0x80($Tbl),$Wi
681         paddd           @MSG[2],$Wi
682         nop
683         sha256rnds2     $ABEF,$CDGH             # 60-63
684         pshufd          \$0x0e,$Wi,$Wi
685         dec             $num
686         nop
687         sha256rnds2     $CDGH,$ABEF
688
689         paddd           $CDGH_SAVE,$CDGH
690         paddd           $ABEF_SAVE,$ABEF
691         jnz             .Loop_shaext
692
693         pshufd          \$0xb1,$CDGH,$CDGH      # DCHG
694         pshufd          \$0x1b,$ABEF,$TMP       # FEBA
695         pshufd          \$0xb1,$ABEF,$ABEF      # BAFE
696         punpckhqdq      $CDGH,$ABEF             # DCBA
697         palignr         \$8,$TMP,$CDGH          # HGFE
698
699         movdqu  $ABEF,($ctx)
700         movdqu  $CDGH,16($ctx)
701 ___
702 $code.=<<___ if ($win64);
703         movaps  -8-5*16(%rax),%xmm6
704         movaps  -8-4*16(%rax),%xmm7
705         movaps  -8-3*16(%rax),%xmm8
706         movaps  -8-2*16(%rax),%xmm9
707         movaps  -8-1*16(%rax),%xmm10
708         mov     %rax,%rsp
709 .Lepilogue_shaext:
710 ___
711 $code.=<<___;
712         ret
713 .size   sha256_block_data_order_shaext,.-sha256_block_data_order_shaext
714 ___
715 }}}
716 {{{
717
718 my $a4=$T1;
719 my ($a,$b,$c,$d,$e,$f,$g,$h);
720
721 sub AUTOLOAD()          # thunk [simplified] 32-bit style perlasm
722 { my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
723   my $arg = pop;
724     $arg = "\$$arg" if ($arg*1 eq $arg);
725     $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
726 }
727
728 sub body_00_15 () {
729         (
730         '($a,$b,$c,$d,$e,$f,$g,$h)=@ROT;'.
731
732         '&ror   ($a0,$Sigma1[2]-$Sigma1[1])',
733         '&mov   ($a,$a1)',
734         '&mov   ($a4,$f)',
735
736         '&ror   ($a1,$Sigma0[2]-$Sigma0[1])',
737         '&xor   ($a0,$e)',
738         '&xor   ($a4,$g)',                      # f^g
739
740         '&ror   ($a0,$Sigma1[1]-$Sigma1[0])',
741         '&xor   ($a1,$a)',
742         '&and   ($a4,$e)',                      # (f^g)&e
743
744         '&xor   ($a0,$e)',
745         '&add   ($h,$SZ*($i&15)."(%rsp)")',     # h+=X[i]+K[i]
746         '&mov   ($a2,$a)',
747
748         '&xor   ($a4,$g)',                      # Ch(e,f,g)=((f^g)&e)^g
749         '&ror   ($a1,$Sigma0[1]-$Sigma0[0])',
750         '&xor   ($a2,$b)',                      # a^b, b^c in next round
751
752         '&add   ($h,$a4)',                      # h+=Ch(e,f,g)
753         '&ror   ($a0,$Sigma1[0])',              # Sigma1(e)
754         '&and   ($a3,$a2)',                     # (b^c)&(a^b)
755
756         '&xor   ($a1,$a)',
757         '&add   ($h,$a0)',                      # h+=Sigma1(e)
758         '&xor   ($a3,$b)',                      # Maj(a,b,c)=Ch(a^b,c,b)
759
760         '&ror   ($a1,$Sigma0[0])',              # Sigma0(a)
761         '&add   ($d,$h)',                       # d+=h
762         '&add   ($h,$a3)',                      # h+=Maj(a,b,c)
763
764         '&mov   ($a0,$d)',
765         '&add   ($a1,$h);'.                     # h+=Sigma0(a)
766         '($a2,$a3) = ($a3,$a2); unshift(@ROT,pop(@ROT)); $i++;'
767         );
768 }
769
770 ######################################################################
771 # SSSE3 code path
772 #
773 if ($SZ==4) {   # SHA256 only
774 my @X = map("%xmm$_",(0..3));
775 my ($t0,$t1,$t2,$t3, $t4,$t5) = map("%xmm$_",(4..9));
776
777 $code.=<<___;
778 .type   ${func}_ssse3,\@function,3
779 .align  64
780 ${func}_ssse3:
781 .cfi_startproc
782 .Lssse3_shortcut:
783         mov     %rsp,%rax               # copy %rsp
784 .cfi_def_cfa_register   %rax
785         push    %rbx
786 .cfi_push       %rbx
787         push    %rbp
788 .cfi_push       %rbp
789         push    %r12
790 .cfi_push       %r12
791         push    %r13
792 .cfi_push       %r13
793         push    %r14
794 .cfi_push       %r14
795         push    %r15
796 .cfi_push       %r15
797         shl     \$4,%rdx                # num*16
798         sub     \$`$framesz+$win64*16*4`,%rsp
799         lea     ($inp,%rdx,$SZ),%rdx    # inp+num*16*$SZ
800         and     \$-64,%rsp              # align stack frame
801         mov     $ctx,$_ctx              # save ctx, 1st arg
802         mov     $inp,$_inp              # save inp, 2nd arh
803         mov     %rdx,$_end              # save end pointer, "3rd" arg
804         mov     %rax,$_rsp              # save copy of %rsp
805 .cfi_cfa_expression     $_rsp,deref,+8
806 ___
807 $code.=<<___ if ($win64);
808         movaps  %xmm6,16*$SZ+32(%rsp)
809         movaps  %xmm7,16*$SZ+48(%rsp)
810         movaps  %xmm8,16*$SZ+64(%rsp)
811         movaps  %xmm9,16*$SZ+80(%rsp)
812 ___
813 $code.=<<___;
814 .Lprologue_ssse3:
815
816         mov     $SZ*0($ctx),$A
817         mov     $SZ*1($ctx),$B
818         mov     $SZ*2($ctx),$C
819         mov     $SZ*3($ctx),$D
820         mov     $SZ*4($ctx),$E
821         mov     $SZ*5($ctx),$F
822         mov     $SZ*6($ctx),$G
823         mov     $SZ*7($ctx),$H
824 ___
825
826 $code.=<<___;
827         #movdqa $TABLE+`$SZ*2*$rounds`+32(%rip),$t4
828         #movdqa $TABLE+`$SZ*2*$rounds`+64(%rip),$t5
829         jmp     .Lloop_ssse3
830 .align  16
831 .Lloop_ssse3:
832         movdqa  $TABLE+`$SZ*2*$rounds`(%rip),$t3
833         movdqu  0x00($inp),@X[0]
834         movdqu  0x10($inp),@X[1]
835         movdqu  0x20($inp),@X[2]
836         pshufb  $t3,@X[0]
837         movdqu  0x30($inp),@X[3]
838         lea     $TABLE(%rip),$Tbl
839         pshufb  $t3,@X[1]
840         movdqa  0x00($Tbl),$t0
841         movdqa  0x20($Tbl),$t1
842         pshufb  $t3,@X[2]
843         paddd   @X[0],$t0
844         movdqa  0x40($Tbl),$t2
845         pshufb  $t3,@X[3]
846         movdqa  0x60($Tbl),$t3
847         paddd   @X[1],$t1
848         paddd   @X[2],$t2
849         paddd   @X[3],$t3
850         movdqa  $t0,0x00(%rsp)
851         mov     $A,$a1
852         movdqa  $t1,0x10(%rsp)
853         mov     $B,$a3
854         movdqa  $t2,0x20(%rsp)
855         xor     $C,$a3                  # magic
856         movdqa  $t3,0x30(%rsp)
857         mov     $E,$a0
858         jmp     .Lssse3_00_47
859
860 .align  16
861 .Lssse3_00_47:
862         sub     \$`-16*2*$SZ`,$Tbl      # size optimization
863 ___
864 sub Xupdate_256_SSSE3 () {
865         (
866         '&movdqa        ($t0,@X[1]);',
867         '&movdqa        ($t3,@X[3])',
868         '&palignr       ($t0,@X[0],$SZ)',       # X[1..4]
869          '&palignr      ($t3,@X[2],$SZ);',      # X[9..12]
870         '&movdqa        ($t1,$t0)',
871         '&movdqa        ($t2,$t0);',
872         '&psrld         ($t0,$sigma0[2])',
873          '&paddd        (@X[0],$t3);',          # X[0..3] += X[9..12]
874         '&psrld         ($t2,$sigma0[0])',
875          '&pshufd       ($t3,@X[3],0b11111010)',# X[14..15]
876         '&pslld         ($t1,8*$SZ-$sigma0[1]);'.
877         '&pxor          ($t0,$t2)',
878         '&psrld         ($t2,$sigma0[1]-$sigma0[0]);'.
879         '&pxor          ($t0,$t1)',
880         '&pslld         ($t1,$sigma0[1]-$sigma0[0]);'.
881         '&pxor          ($t0,$t2);',
882          '&movdqa       ($t2,$t3)',
883         '&pxor          ($t0,$t1);',            # sigma0(X[1..4])
884          '&psrld        ($t3,$sigma1[2])',
885         '&paddd         (@X[0],$t0);',          # X[0..3] += sigma0(X[1..4])
886          '&psrlq        ($t2,$sigma1[0])',
887          '&pxor         ($t3,$t2);',
888          '&psrlq        ($t2,$sigma1[1]-$sigma1[0])',
889          '&pxor         ($t3,$t2)',
890          '&pshufb       ($t3,$t4)',             # sigma1(X[14..15])
891         '&paddd         (@X[0],$t3)',           # X[0..1] += sigma1(X[14..15])
892          '&pshufd       ($t3,@X[0],0b01010000)',# X[16..17]
893          '&movdqa       ($t2,$t3);',
894          '&psrld        ($t3,$sigma1[2])',
895          '&psrlq        ($t2,$sigma1[0])',
896          '&pxor         ($t3,$t2);',
897          '&psrlq        ($t2,$sigma1[1]-$sigma1[0])',
898          '&pxor         ($t3,$t2);',
899         '&movdqa        ($t2,16*2*$j."($Tbl)")',
900          '&pshufb       ($t3,$t5)',
901         '&paddd         (@X[0],$t3)'            # X[2..3] += sigma1(X[16..17])
902         );
903 }
904
905 sub SSSE3_256_00_47 () {
906 my $j = shift;
907 my $body = shift;
908 my @X = @_;
909 my @insns = (&$body,&$body,&$body,&$body);      # 104 instructions
910
911     if (0) {
912         foreach (Xupdate_256_SSSE3()) {         # 36 instructions
913             eval;
914             eval(shift(@insns));
915             eval(shift(@insns));
916             eval(shift(@insns));
917         }
918     } else {                    # squeeze extra 4% on Westmere and 19% on Atom
919           eval(shift(@insns));  #@
920         &movdqa         ($t0,@X[1]);
921           eval(shift(@insns));
922           eval(shift(@insns));
923         &movdqa         ($t3,@X[3]);
924           eval(shift(@insns));  #@
925           eval(shift(@insns));
926           eval(shift(@insns));
927           eval(shift(@insns));  #@
928           eval(shift(@insns));
929         &palignr        ($t0,@X[0],$SZ);        # X[1..4]
930           eval(shift(@insns));
931           eval(shift(@insns));
932          &palignr       ($t3,@X[2],$SZ);        # X[9..12]
933           eval(shift(@insns));
934           eval(shift(@insns));
935           eval(shift(@insns));
936           eval(shift(@insns));  #@
937         &movdqa         ($t1,$t0);
938           eval(shift(@insns));
939           eval(shift(@insns));
940         &movdqa         ($t2,$t0);
941           eval(shift(@insns));  #@
942           eval(shift(@insns));
943         &psrld          ($t0,$sigma0[2]);
944           eval(shift(@insns));
945           eval(shift(@insns));
946           eval(shift(@insns));
947          &paddd         (@X[0],$t3);            # X[0..3] += X[9..12]
948           eval(shift(@insns));  #@
949           eval(shift(@insns));
950         &psrld          ($t2,$sigma0[0]);
951           eval(shift(@insns));
952           eval(shift(@insns));
953          &pshufd        ($t3,@X[3],0b11111010); # X[4..15]
954           eval(shift(@insns));
955           eval(shift(@insns));  #@
956         &pslld          ($t1,8*$SZ-$sigma0[1]);
957           eval(shift(@insns));
958           eval(shift(@insns));
959         &pxor           ($t0,$t2);
960           eval(shift(@insns));  #@
961           eval(shift(@insns));
962           eval(shift(@insns));
963           eval(shift(@insns));  #@
964         &psrld          ($t2,$sigma0[1]-$sigma0[0]);
965           eval(shift(@insns));
966         &pxor           ($t0,$t1);
967           eval(shift(@insns));
968           eval(shift(@insns));
969         &pslld          ($t1,$sigma0[1]-$sigma0[0]);
970           eval(shift(@insns));
971           eval(shift(@insns));
972         &pxor           ($t0,$t2);
973           eval(shift(@insns));
974           eval(shift(@insns));  #@
975          &movdqa        ($t2,$t3);
976           eval(shift(@insns));
977           eval(shift(@insns));
978         &pxor           ($t0,$t1);              # sigma0(X[1..4])
979           eval(shift(@insns));  #@
980           eval(shift(@insns));
981           eval(shift(@insns));
982          &psrld         ($t3,$sigma1[2]);
983           eval(shift(@insns));
984           eval(shift(@insns));
985         &paddd          (@X[0],$t0);            # X[0..3] += sigma0(X[1..4])
986           eval(shift(@insns));  #@
987           eval(shift(@insns));
988          &psrlq         ($t2,$sigma1[0]);
989           eval(shift(@insns));
990           eval(shift(@insns));
991           eval(shift(@insns));
992          &pxor          ($t3,$t2);
993           eval(shift(@insns));  #@
994           eval(shift(@insns));
995           eval(shift(@insns));
996           eval(shift(@insns));  #@
997          &psrlq         ($t2,$sigma1[1]-$sigma1[0]);
998           eval(shift(@insns));
999           eval(shift(@insns));
1000          &pxor          ($t3,$t2);
1001           eval(shift(@insns));  #@
1002           eval(shift(@insns));
1003           eval(shift(@insns));
1004          #&pshufb       ($t3,$t4);              # sigma1(X[14..15])
1005          &pshufd        ($t3,$t3,0b10000000);
1006           eval(shift(@insns));
1007           eval(shift(@insns));
1008           eval(shift(@insns));
1009          &psrldq        ($t3,8);
1010           eval(shift(@insns));
1011           eval(shift(@insns));  #@
1012           eval(shift(@insns));
1013           eval(shift(@insns));
1014           eval(shift(@insns));  #@
1015         &paddd          (@X[0],$t3);            # X[0..1] += sigma1(X[14..15])
1016           eval(shift(@insns));
1017           eval(shift(@insns));
1018           eval(shift(@insns));
1019          &pshufd        ($t3,@X[0],0b01010000); # X[16..17]
1020           eval(shift(@insns));
1021           eval(shift(@insns));  #@
1022           eval(shift(@insns));
1023          &movdqa        ($t2,$t3);
1024           eval(shift(@insns));
1025           eval(shift(@insns));
1026          &psrld         ($t3,$sigma1[2]);
1027           eval(shift(@insns));
1028           eval(shift(@insns));  #@
1029          &psrlq         ($t2,$sigma1[0]);
1030           eval(shift(@insns));
1031           eval(shift(@insns));
1032          &pxor          ($t3,$t2);
1033           eval(shift(@insns));  #@
1034           eval(shift(@insns));
1035           eval(shift(@insns));
1036           eval(shift(@insns));  #@
1037           eval(shift(@insns));
1038          &psrlq         ($t2,$sigma1[1]-$sigma1[0]);
1039           eval(shift(@insns));
1040           eval(shift(@insns));
1041           eval(shift(@insns));
1042          &pxor          ($t3,$t2);
1043           eval(shift(@insns));
1044           eval(shift(@insns));
1045           eval(shift(@insns));  #@
1046          #&pshufb       ($t3,$t5);
1047          &pshufd        ($t3,$t3,0b00001000);
1048           eval(shift(@insns));
1049           eval(shift(@insns));
1050         &movdqa         ($t2,16*2*$j."($Tbl)");
1051           eval(shift(@insns));  #@
1052           eval(shift(@insns));
1053          &pslldq        ($t3,8);
1054           eval(shift(@insns));
1055           eval(shift(@insns));
1056           eval(shift(@insns));
1057         &paddd          (@X[0],$t3);            # X[2..3] += sigma1(X[16..17])
1058           eval(shift(@insns));  #@
1059           eval(shift(@insns));
1060           eval(shift(@insns));
1061     }
1062         &paddd          ($t2,@X[0]);
1063           foreach (@insns) { eval; }            # remaining instructions
1064         &movdqa         (16*$j."(%rsp)",$t2);
1065 }
1066
1067     for ($i=0,$j=0; $j<4; $j++) {
1068         &SSSE3_256_00_47($j,\&body_00_15,@X);
1069         push(@X,shift(@X));                     # rotate(@X)
1070     }
1071         &cmpb   ($SZ-1+16*2*$SZ."($Tbl)",0);
1072         &jne    (".Lssse3_00_47");
1073
1074     for ($i=0; $i<16; ) {
1075         foreach(body_00_15()) { eval; }
1076     }
1077 $code.=<<___;
1078         mov     $_ctx,$ctx
1079         mov     $a1,$A
1080
1081         add     $SZ*0($ctx),$A
1082         lea     16*$SZ($inp),$inp
1083         add     $SZ*1($ctx),$B
1084         add     $SZ*2($ctx),$C
1085         add     $SZ*3($ctx),$D
1086         add     $SZ*4($ctx),$E
1087         add     $SZ*5($ctx),$F
1088         add     $SZ*6($ctx),$G
1089         add     $SZ*7($ctx),$H
1090
1091         cmp     $_end,$inp
1092
1093         mov     $A,$SZ*0($ctx)
1094         mov     $B,$SZ*1($ctx)
1095         mov     $C,$SZ*2($ctx)
1096         mov     $D,$SZ*3($ctx)
1097         mov     $E,$SZ*4($ctx)
1098         mov     $F,$SZ*5($ctx)
1099         mov     $G,$SZ*6($ctx)
1100         mov     $H,$SZ*7($ctx)
1101         jb      .Lloop_ssse3
1102
1103         mov     $_rsp,%rsi
1104 .cfi_def_cfa    %rsi,8
1105 ___
1106 $code.=<<___ if ($win64);
1107         movaps  16*$SZ+32(%rsp),%xmm6
1108         movaps  16*$SZ+48(%rsp),%xmm7
1109         movaps  16*$SZ+64(%rsp),%xmm8
1110         movaps  16*$SZ+80(%rsp),%xmm9
1111 ___
1112 $code.=<<___;
1113         mov     -48(%rsi),%r15
1114 .cfi_restore    %r15
1115         mov     -40(%rsi),%r14
1116 .cfi_restore    %r14
1117         mov     -32(%rsi),%r13
1118 .cfi_restore    %r13
1119         mov     -24(%rsi),%r12
1120 .cfi_restore    %r12
1121         mov     -16(%rsi),%rbp
1122 .cfi_restore    %rbp
1123         mov     -8(%rsi),%rbx
1124 .cfi_restore    %rbx
1125         lea     (%rsi),%rsp
1126 .cfi_def_cfa_register   %rsp
1127 .Lepilogue_ssse3:
1128         ret
1129 .cfi_endproc
1130 .size   ${func}_ssse3,.-${func}_ssse3
1131 ___
1132 }
1133
1134 if ($avx) {{
1135 ######################################################################
1136 # XOP code path
1137 #
1138 if ($SZ==8) {   # SHA512 only
1139 $code.=<<___;
1140 .type   ${func}_xop,\@function,3
1141 .align  64
1142 ${func}_xop:
1143 .cfi_startproc
1144 .Lxop_shortcut:
1145         mov     %rsp,%rax               # copy %rsp
1146 .cfi_def_cfa_register   %rax
1147         push    %rbx
1148 .cfi_push       %rbx
1149         push    %rbp
1150 .cfi_push       %rbp
1151         push    %r12
1152 .cfi_push       %r12
1153         push    %r13
1154 .cfi_push       %r13
1155         push    %r14
1156 .cfi_push       %r14
1157         push    %r15
1158 .cfi_push       %r15
1159         shl     \$4,%rdx                # num*16
1160         sub     \$`$framesz+$win64*16*($SZ==4?4:6)`,%rsp
1161         lea     ($inp,%rdx,$SZ),%rdx    # inp+num*16*$SZ
1162         and     \$-64,%rsp              # align stack frame
1163         mov     $ctx,$_ctx              # save ctx, 1st arg
1164         mov     $inp,$_inp              # save inp, 2nd arh
1165         mov     %rdx,$_end              # save end pointer, "3rd" arg
1166         mov     %rax,$_rsp              # save copy of %rsp
1167 .cfi_cfa_expression     $_rsp,deref,+8
1168 ___
1169 $code.=<<___ if ($win64);
1170         movaps  %xmm6,16*$SZ+32(%rsp)
1171         movaps  %xmm7,16*$SZ+48(%rsp)
1172         movaps  %xmm8,16*$SZ+64(%rsp)
1173         movaps  %xmm9,16*$SZ+80(%rsp)
1174 ___
1175 $code.=<<___ if ($win64 && $SZ>4);
1176         movaps  %xmm10,16*$SZ+96(%rsp)
1177         movaps  %xmm11,16*$SZ+112(%rsp)
1178 ___
1179 $code.=<<___;
1180 .Lprologue_xop:
1181
1182         vzeroupper
1183         mov     $SZ*0($ctx),$A
1184         mov     $SZ*1($ctx),$B
1185         mov     $SZ*2($ctx),$C
1186         mov     $SZ*3($ctx),$D
1187         mov     $SZ*4($ctx),$E
1188         mov     $SZ*5($ctx),$F
1189         mov     $SZ*6($ctx),$G
1190         mov     $SZ*7($ctx),$H
1191         jmp     .Lloop_xop
1192 ___
1193                                         if ($SZ==4) {   # SHA256
1194     my @X = map("%xmm$_",(0..3));
1195     my ($t0,$t1,$t2,$t3) = map("%xmm$_",(4..7));
1196
1197 $code.=<<___;
1198 .align  16
1199 .Lloop_xop:
1200         vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3
1201         vmovdqu 0x00($inp),@X[0]
1202         vmovdqu 0x10($inp),@X[1]
1203         vmovdqu 0x20($inp),@X[2]
1204         vmovdqu 0x30($inp),@X[3]
1205         vpshufb $t3,@X[0],@X[0]
1206         lea     $TABLE(%rip),$Tbl
1207         vpshufb $t3,@X[1],@X[1]
1208         vpshufb $t3,@X[2],@X[2]
1209         vpaddd  0x00($Tbl),@X[0],$t0
1210         vpshufb $t3,@X[3],@X[3]
1211         vpaddd  0x20($Tbl),@X[1],$t1
1212         vpaddd  0x40($Tbl),@X[2],$t2
1213         vpaddd  0x60($Tbl),@X[3],$t3
1214         vmovdqa $t0,0x00(%rsp)
1215         mov     $A,$a1
1216         vmovdqa $t1,0x10(%rsp)
1217         mov     $B,$a3
1218         vmovdqa $t2,0x20(%rsp)
1219         xor     $C,$a3                  # magic
1220         vmovdqa $t3,0x30(%rsp)
1221         mov     $E,$a0
1222         jmp     .Lxop_00_47
1223
1224 .align  16
1225 .Lxop_00_47:
1226         sub     \$`-16*2*$SZ`,$Tbl      # size optimization
1227 ___
1228 sub XOP_256_00_47 () {
1229 my $j = shift;
1230 my $body = shift;
1231 my @X = @_;
1232 my @insns = (&$body,&$body,&$body,&$body);      # 104 instructions
1233
1234         &vpalignr       ($t0,@X[1],@X[0],$SZ);  # X[1..4]
1235           eval(shift(@insns));
1236           eval(shift(@insns));
1237          &vpalignr      ($t3,@X[3],@X[2],$SZ);  # X[9..12]
1238           eval(shift(@insns));
1239           eval(shift(@insns));
1240         &vprotd         ($t1,$t0,8*$SZ-$sigma0[1]);
1241           eval(shift(@insns));
1242           eval(shift(@insns));
1243         &vpsrld         ($t0,$t0,$sigma0[2]);
1244           eval(shift(@insns));
1245           eval(shift(@insns));
1246          &vpaddd        (@X[0],@X[0],$t3);      # X[0..3] += X[9..12]
1247           eval(shift(@insns));
1248           eval(shift(@insns));
1249           eval(shift(@insns));
1250           eval(shift(@insns));
1251         &vprotd         ($t2,$t1,$sigma0[1]-$sigma0[0]);
1252           eval(shift(@insns));
1253           eval(shift(@insns));
1254         &vpxor          ($t0,$t0,$t1);
1255           eval(shift(@insns));
1256           eval(shift(@insns));
1257           eval(shift(@insns));
1258           eval(shift(@insns));
1259          &vprotd        ($t3,@X[3],8*$SZ-$sigma1[1]);
1260           eval(shift(@insns));
1261           eval(shift(@insns));
1262         &vpxor          ($t0,$t0,$t2);          # sigma0(X[1..4])
1263           eval(shift(@insns));
1264           eval(shift(@insns));
1265          &vpsrld        ($t2,@X[3],$sigma1[2]);
1266           eval(shift(@insns));
1267           eval(shift(@insns));
1268         &vpaddd         (@X[0],@X[0],$t0);      # X[0..3] += sigma0(X[1..4])
1269           eval(shift(@insns));
1270           eval(shift(@insns));
1271          &vprotd        ($t1,$t3,$sigma1[1]-$sigma1[0]);
1272           eval(shift(@insns));
1273           eval(shift(@insns));
1274          &vpxor         ($t3,$t3,$t2);
1275           eval(shift(@insns));
1276           eval(shift(@insns));
1277           eval(shift(@insns));
1278           eval(shift(@insns));
1279          &vpxor         ($t3,$t3,$t1);          # sigma1(X[14..15])
1280           eval(shift(@insns));
1281           eval(shift(@insns));
1282           eval(shift(@insns));
1283           eval(shift(@insns));
1284         &vpsrldq        ($t3,$t3,8);
1285           eval(shift(@insns));
1286           eval(shift(@insns));
1287           eval(shift(@insns));
1288           eval(shift(@insns));
1289         &vpaddd         (@X[0],@X[0],$t3);      # X[0..1] += sigma1(X[14..15])
1290           eval(shift(@insns));
1291           eval(shift(@insns));
1292           eval(shift(@insns));
1293           eval(shift(@insns));
1294          &vprotd        ($t3,@X[0],8*$SZ-$sigma1[1]);
1295           eval(shift(@insns));
1296           eval(shift(@insns));
1297          &vpsrld        ($t2,@X[0],$sigma1[2]);
1298           eval(shift(@insns));
1299           eval(shift(@insns));
1300          &vprotd        ($t1,$t3,$sigma1[1]-$sigma1[0]);
1301           eval(shift(@insns));
1302           eval(shift(@insns));
1303          &vpxor         ($t3,$t3,$t2);
1304           eval(shift(@insns));
1305           eval(shift(@insns));
1306           eval(shift(@insns));
1307           eval(shift(@insns));
1308          &vpxor         ($t3,$t3,$t1);          # sigma1(X[16..17])
1309           eval(shift(@insns));
1310           eval(shift(@insns));
1311           eval(shift(@insns));
1312           eval(shift(@insns));
1313         &vpslldq        ($t3,$t3,8);            # 22 instructions
1314           eval(shift(@insns));
1315           eval(shift(@insns));
1316           eval(shift(@insns));
1317           eval(shift(@insns));
1318         &vpaddd         (@X[0],@X[0],$t3);      # X[2..3] += sigma1(X[16..17])
1319           eval(shift(@insns));
1320           eval(shift(@insns));
1321           eval(shift(@insns));
1322           eval(shift(@insns));
1323         &vpaddd         ($t2,@X[0],16*2*$j."($Tbl)");
1324           foreach (@insns) { eval; }            # remaining instructions
1325         &vmovdqa        (16*$j."(%rsp)",$t2);
1326 }
1327
1328     for ($i=0,$j=0; $j<4; $j++) {
1329         &XOP_256_00_47($j,\&body_00_15,@X);
1330         push(@X,shift(@X));                     # rotate(@X)
1331     }
1332         &cmpb   ($SZ-1+16*2*$SZ."($Tbl)",0);
1333         &jne    (".Lxop_00_47");
1334
1335     for ($i=0; $i<16; ) {
1336         foreach(body_00_15()) { eval; }
1337     }
1338
1339                                         } else {        # SHA512
1340     my @X = map("%xmm$_",(0..7));
1341     my ($t0,$t1,$t2,$t3) = map("%xmm$_",(8..11));
1342
1343 $code.=<<___;
1344 .align  16
1345 .Lloop_xop:
1346         vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3
1347         vmovdqu 0x00($inp),@X[0]
1348         lea     $TABLE+0x80(%rip),$Tbl  # size optimization
1349         vmovdqu 0x10($inp),@X[1]
1350         vmovdqu 0x20($inp),@X[2]
1351         vpshufb $t3,@X[0],@X[0]
1352         vmovdqu 0x30($inp),@X[3]
1353         vpshufb $t3,@X[1],@X[1]
1354         vmovdqu 0x40($inp),@X[4]
1355         vpshufb $t3,@X[2],@X[2]
1356         vmovdqu 0x50($inp),@X[5]
1357         vpshufb $t3,@X[3],@X[3]
1358         vmovdqu 0x60($inp),@X[6]
1359         vpshufb $t3,@X[4],@X[4]
1360         vmovdqu 0x70($inp),@X[7]
1361         vpshufb $t3,@X[5],@X[5]
1362         vpaddq  -0x80($Tbl),@X[0],$t0
1363         vpshufb $t3,@X[6],@X[6]
1364         vpaddq  -0x60($Tbl),@X[1],$t1
1365         vpshufb $t3,@X[7],@X[7]
1366         vpaddq  -0x40($Tbl),@X[2],$t2
1367         vpaddq  -0x20($Tbl),@X[3],$t3
1368         vmovdqa $t0,0x00(%rsp)
1369         vpaddq  0x00($Tbl),@X[4],$t0
1370         vmovdqa $t1,0x10(%rsp)
1371         vpaddq  0x20($Tbl),@X[5],$t1
1372         vmovdqa $t2,0x20(%rsp)
1373         vpaddq  0x40($Tbl),@X[6],$t2
1374         vmovdqa $t3,0x30(%rsp)
1375         vpaddq  0x60($Tbl),@X[7],$t3
1376         vmovdqa $t0,0x40(%rsp)
1377         mov     $A,$a1
1378         vmovdqa $t1,0x50(%rsp)
1379         mov     $B,$a3
1380         vmovdqa $t2,0x60(%rsp)
1381         xor     $C,$a3                  # magic
1382         vmovdqa $t3,0x70(%rsp)
1383         mov     $E,$a0
1384         jmp     .Lxop_00_47
1385
1386 .align  16
1387 .Lxop_00_47:
1388         add     \$`16*2*$SZ`,$Tbl
1389 ___
1390 sub XOP_512_00_47 () {
1391 my $j = shift;
1392 my $body = shift;
1393 my @X = @_;
1394 my @insns = (&$body,&$body);                    # 52 instructions
1395
1396         &vpalignr       ($t0,@X[1],@X[0],$SZ);  # X[1..2]
1397           eval(shift(@insns));
1398           eval(shift(@insns));
1399          &vpalignr      ($t3,@X[5],@X[4],$SZ);  # X[9..10]
1400           eval(shift(@insns));
1401           eval(shift(@insns));
1402         &vprotq         ($t1,$t0,8*$SZ-$sigma0[1]);
1403           eval(shift(@insns));
1404           eval(shift(@insns));
1405         &vpsrlq         ($t0,$t0,$sigma0[2]);
1406           eval(shift(@insns));
1407           eval(shift(@insns));
1408          &vpaddq        (@X[0],@X[0],$t3);      # X[0..1] += X[9..10]
1409           eval(shift(@insns));
1410           eval(shift(@insns));
1411           eval(shift(@insns));
1412           eval(shift(@insns));
1413         &vprotq         ($t2,$t1,$sigma0[1]-$sigma0[0]);
1414           eval(shift(@insns));
1415           eval(shift(@insns));
1416         &vpxor          ($t0,$t0,$t1);
1417           eval(shift(@insns));
1418           eval(shift(@insns));
1419           eval(shift(@insns));
1420           eval(shift(@insns));
1421          &vprotq        ($t3,@X[7],8*$SZ-$sigma1[1]);
1422           eval(shift(@insns));
1423           eval(shift(@insns));
1424         &vpxor          ($t0,$t0,$t2);          # sigma0(X[1..2])
1425           eval(shift(@insns));
1426           eval(shift(@insns));
1427          &vpsrlq        ($t2,@X[7],$sigma1[2]);
1428           eval(shift(@insns));
1429           eval(shift(@insns));
1430         &vpaddq         (@X[0],@X[0],$t0);      # X[0..1] += sigma0(X[1..2])
1431           eval(shift(@insns));
1432           eval(shift(@insns));
1433          &vprotq        ($t1,$t3,$sigma1[1]-$sigma1[0]);
1434           eval(shift(@insns));
1435           eval(shift(@insns));
1436          &vpxor         ($t3,$t3,$t2);
1437           eval(shift(@insns));
1438           eval(shift(@insns));
1439           eval(shift(@insns));
1440           eval(shift(@insns));
1441          &vpxor         ($t3,$t3,$t1);          # sigma1(X[14..15])
1442           eval(shift(@insns));
1443           eval(shift(@insns));
1444           eval(shift(@insns));
1445           eval(shift(@insns));
1446         &vpaddq         (@X[0],@X[0],$t3);      # X[0..1] += sigma1(X[14..15])
1447           eval(shift(@insns));
1448           eval(shift(@insns));
1449           eval(shift(@insns));
1450           eval(shift(@insns));
1451         &vpaddq         ($t2,@X[0],16*2*$j-0x80."($Tbl)");
1452           foreach (@insns) { eval; }            # remaining instructions
1453         &vmovdqa        (16*$j."(%rsp)",$t2);
1454 }
1455
1456     for ($i=0,$j=0; $j<8; $j++) {
1457         &XOP_512_00_47($j,\&body_00_15,@X);
1458         push(@X,shift(@X));                     # rotate(@X)
1459     }
1460         &cmpb   ($SZ-1+16*2*$SZ-0x80."($Tbl)",0);
1461         &jne    (".Lxop_00_47");
1462
1463     for ($i=0; $i<16; ) {
1464         foreach(body_00_15()) { eval; }
1465     }
1466 }
1467 $code.=<<___;
1468         mov     $_ctx,$ctx
1469         mov     $a1,$A
1470
1471         add     $SZ*0($ctx),$A
1472         lea     16*$SZ($inp),$inp
1473         add     $SZ*1($ctx),$B
1474         add     $SZ*2($ctx),$C
1475         add     $SZ*3($ctx),$D
1476         add     $SZ*4($ctx),$E
1477         add     $SZ*5($ctx),$F
1478         add     $SZ*6($ctx),$G
1479         add     $SZ*7($ctx),$H
1480
1481         cmp     $_end,$inp
1482
1483         mov     $A,$SZ*0($ctx)
1484         mov     $B,$SZ*1($ctx)
1485         mov     $C,$SZ*2($ctx)
1486         mov     $D,$SZ*3($ctx)
1487         mov     $E,$SZ*4($ctx)
1488         mov     $F,$SZ*5($ctx)
1489         mov     $G,$SZ*6($ctx)
1490         mov     $H,$SZ*7($ctx)
1491         jb      .Lloop_xop
1492
1493         mov     $_rsp,%rsi
1494 .cfi_def_cfa    %rsi,8
1495         vzeroupper
1496 ___
1497 $code.=<<___ if ($win64);
1498         movaps  16*$SZ+32(%rsp),%xmm6
1499         movaps  16*$SZ+48(%rsp),%xmm7
1500         movaps  16*$SZ+64(%rsp),%xmm8
1501         movaps  16*$SZ+80(%rsp),%xmm9
1502 ___
1503 $code.=<<___ if ($win64 && $SZ>4);
1504         movaps  16*$SZ+96(%rsp),%xmm10
1505         movaps  16*$SZ+112(%rsp),%xmm11
1506 ___
1507 $code.=<<___;
1508         mov     -48(%rsi),%r15
1509 .cfi_restore    %r15
1510         mov     -40(%rsi),%r14
1511 .cfi_restore    %r14
1512         mov     -32(%rsi),%r13
1513 .cfi_restore    %r13
1514         mov     -24(%rsi),%r12
1515 .cfi_restore    %r12
1516         mov     -16(%rsi),%rbp
1517 .cfi_restore    %rbp
1518         mov     -8(%rsi),%rbx
1519 .cfi_restore    %rbx
1520         lea     (%rsi),%rsp
1521 .cfi_def_cfa_register   %rsp
1522 .Lepilogue_xop:
1523         ret
1524 .cfi_endproc
1525 .size   ${func}_xop,.-${func}_xop
1526 ___
1527 }
1528 ######################################################################
1529 # AVX+shrd code path
1530 #
1531 local *ror = sub { &shrd(@_[0],@_) };
1532
1533 $code.=<<___;
1534 .type   ${func}_avx,\@function,3
1535 .align  64
1536 ${func}_avx:
1537 .cfi_startproc
1538 .Lavx_shortcut:
1539         mov     %rsp,%rax               # copy %rsp
1540 .cfi_def_cfa_register   %rax
1541         push    %rbx
1542 .cfi_push       %rbx
1543         push    %rbp
1544 .cfi_push       %rbp
1545         push    %r12
1546 .cfi_push       %r12
1547         push    %r13
1548 .cfi_push       %r13
1549         push    %r14
1550 .cfi_push       %r14
1551         push    %r15
1552 .cfi_push       %r15
1553         shl     \$4,%rdx                # num*16
1554         sub     \$`$framesz+$win64*16*($SZ==4?4:6)`,%rsp
1555         lea     ($inp,%rdx,$SZ),%rdx    # inp+num*16*$SZ
1556         and     \$-64,%rsp              # align stack frame
1557         mov     $ctx,$_ctx              # save ctx, 1st arg
1558         mov     $inp,$_inp              # save inp, 2nd arh
1559         mov     %rdx,$_end              # save end pointer, "3rd" arg
1560         mov     %rax,$_rsp              # save copy of %rsp
1561 .cfi_cfa_expression     $_rsp,deref,+8
1562 ___
1563 $code.=<<___ if ($win64);
1564         movaps  %xmm6,16*$SZ+32(%rsp)
1565         movaps  %xmm7,16*$SZ+48(%rsp)
1566         movaps  %xmm8,16*$SZ+64(%rsp)
1567         movaps  %xmm9,16*$SZ+80(%rsp)
1568 ___
1569 $code.=<<___ if ($win64 && $SZ>4);
1570         movaps  %xmm10,16*$SZ+96(%rsp)
1571         movaps  %xmm11,16*$SZ+112(%rsp)
1572 ___
1573 $code.=<<___;
1574 .Lprologue_avx:
1575
1576         vzeroupper
1577         mov     $SZ*0($ctx),$A
1578         mov     $SZ*1($ctx),$B
1579         mov     $SZ*2($ctx),$C
1580         mov     $SZ*3($ctx),$D
1581         mov     $SZ*4($ctx),$E
1582         mov     $SZ*5($ctx),$F
1583         mov     $SZ*6($ctx),$G
1584         mov     $SZ*7($ctx),$H
1585 ___
1586                                         if ($SZ==4) {   # SHA256
1587     my @X = map("%xmm$_",(0..3));
1588     my ($t0,$t1,$t2,$t3, $t4,$t5) = map("%xmm$_",(4..9));
1589
1590 $code.=<<___;
1591         vmovdqa $TABLE+`$SZ*2*$rounds`+32(%rip),$t4
1592         vmovdqa $TABLE+`$SZ*2*$rounds`+64(%rip),$t5
1593         jmp     .Lloop_avx
1594 .align  16
1595 .Lloop_avx:
1596         vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3
1597         vmovdqu 0x00($inp),@X[0]
1598         vmovdqu 0x10($inp),@X[1]
1599         vmovdqu 0x20($inp),@X[2]
1600         vmovdqu 0x30($inp),@X[3]
1601         vpshufb $t3,@X[0],@X[0]
1602         lea     $TABLE(%rip),$Tbl
1603         vpshufb $t3,@X[1],@X[1]
1604         vpshufb $t3,@X[2],@X[2]
1605         vpaddd  0x00($Tbl),@X[0],$t0
1606         vpshufb $t3,@X[3],@X[3]
1607         vpaddd  0x20($Tbl),@X[1],$t1
1608         vpaddd  0x40($Tbl),@X[2],$t2
1609         vpaddd  0x60($Tbl),@X[3],$t3
1610         vmovdqa $t0,0x00(%rsp)
1611         mov     $A,$a1
1612         vmovdqa $t1,0x10(%rsp)
1613         mov     $B,$a3
1614         vmovdqa $t2,0x20(%rsp)
1615         xor     $C,$a3                  # magic
1616         vmovdqa $t3,0x30(%rsp)
1617         mov     $E,$a0
1618         jmp     .Lavx_00_47
1619
1620 .align  16
1621 .Lavx_00_47:
1622         sub     \$`-16*2*$SZ`,$Tbl      # size optimization
1623 ___
1624 sub Xupdate_256_AVX () {
1625         (
1626         '&vpalignr      ($t0,@X[1],@X[0],$SZ)', # X[1..4]
1627          '&vpalignr     ($t3,@X[3],@X[2],$SZ)', # X[9..12]
1628         '&vpsrld        ($t2,$t0,$sigma0[0]);',
1629          '&vpaddd       (@X[0],@X[0],$t3)',     # X[0..3] += X[9..12]
1630         '&vpsrld        ($t3,$t0,$sigma0[2])',
1631         '&vpslld        ($t1,$t0,8*$SZ-$sigma0[1]);',
1632         '&vpxor         ($t0,$t3,$t2)',
1633          '&vpshufd      ($t3,@X[3],0b11111010)',# X[14..15]
1634         '&vpsrld        ($t2,$t2,$sigma0[1]-$sigma0[0]);',
1635         '&vpxor         ($t0,$t0,$t1)',
1636         '&vpslld        ($t1,$t1,$sigma0[1]-$sigma0[0]);',
1637         '&vpxor         ($t0,$t0,$t2)',
1638          '&vpsrld       ($t2,$t3,$sigma1[2]);',
1639         '&vpxor         ($t0,$t0,$t1)',         # sigma0(X[1..4])
1640          '&vpsrlq       ($t3,$t3,$sigma1[0]);',
1641         '&vpaddd        (@X[0],@X[0],$t0)',     # X[0..3] += sigma0(X[1..4])
1642          '&vpxor        ($t2,$t2,$t3);',
1643          '&vpsrlq       ($t3,$t3,$sigma1[1]-$sigma1[0])',
1644          '&vpxor        ($t2,$t2,$t3)',
1645          '&vpshufb      ($t2,$t2,$t4)',         # sigma1(X[14..15])
1646         '&vpaddd        (@X[0],@X[0],$t2)',     # X[0..1] += sigma1(X[14..15])
1647          '&vpshufd      ($t3,@X[0],0b01010000)',# X[16..17]
1648          '&vpsrld       ($t2,$t3,$sigma1[2])',
1649          '&vpsrlq       ($t3,$t3,$sigma1[0])',
1650          '&vpxor        ($t2,$t2,$t3);',
1651          '&vpsrlq       ($t3,$t3,$sigma1[1]-$sigma1[0])',
1652          '&vpxor        ($t2,$t2,$t3)',
1653          '&vpshufb      ($t2,$t2,$t5)',
1654         '&vpaddd        (@X[0],@X[0],$t2)'      # X[2..3] += sigma1(X[16..17])
1655         );
1656 }
1657
1658 sub AVX_256_00_47 () {
1659 my $j = shift;
1660 my $body = shift;
1661 my @X = @_;
1662 my @insns = (&$body,&$body,&$body,&$body);      # 104 instructions
1663
1664         foreach (Xupdate_256_AVX()) {           # 29 instructions
1665             eval;
1666             eval(shift(@insns));
1667             eval(shift(@insns));
1668             eval(shift(@insns));
1669         }
1670         &vpaddd         ($t2,@X[0],16*2*$j."($Tbl)");
1671           foreach (@insns) { eval; }            # remaining instructions
1672         &vmovdqa        (16*$j."(%rsp)",$t2);
1673 }
1674
1675     for ($i=0,$j=0; $j<4; $j++) {
1676         &AVX_256_00_47($j,\&body_00_15,@X);
1677         push(@X,shift(@X));                     # rotate(@X)
1678     }
1679         &cmpb   ($SZ-1+16*2*$SZ."($Tbl)",0);
1680         &jne    (".Lavx_00_47");
1681
1682     for ($i=0; $i<16; ) {
1683         foreach(body_00_15()) { eval; }
1684     }
1685
1686                                         } else {        # SHA512
1687     my @X = map("%xmm$_",(0..7));
1688     my ($t0,$t1,$t2,$t3) = map("%xmm$_",(8..11));
1689
1690 $code.=<<___;
1691         jmp     .Lloop_avx
1692 .align  16
1693 .Lloop_avx:
1694         vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3
1695         vmovdqu 0x00($inp),@X[0]
1696         lea     $TABLE+0x80(%rip),$Tbl  # size optimization
1697         vmovdqu 0x10($inp),@X[1]
1698         vmovdqu 0x20($inp),@X[2]
1699         vpshufb $t3,@X[0],@X[0]
1700         vmovdqu 0x30($inp),@X[3]
1701         vpshufb $t3,@X[1],@X[1]
1702         vmovdqu 0x40($inp),@X[4]
1703         vpshufb $t3,@X[2],@X[2]
1704         vmovdqu 0x50($inp),@X[5]
1705         vpshufb $t3,@X[3],@X[3]
1706         vmovdqu 0x60($inp),@X[6]
1707         vpshufb $t3,@X[4],@X[4]
1708         vmovdqu 0x70($inp),@X[7]
1709         vpshufb $t3,@X[5],@X[5]
1710         vpaddq  -0x80($Tbl),@X[0],$t0
1711         vpshufb $t3,@X[6],@X[6]
1712         vpaddq  -0x60($Tbl),@X[1],$t1
1713         vpshufb $t3,@X[7],@X[7]
1714         vpaddq  -0x40($Tbl),@X[2],$t2
1715         vpaddq  -0x20($Tbl),@X[3],$t3
1716         vmovdqa $t0,0x00(%rsp)
1717         vpaddq  0x00($Tbl),@X[4],$t0
1718         vmovdqa $t1,0x10(%rsp)
1719         vpaddq  0x20($Tbl),@X[5],$t1
1720         vmovdqa $t2,0x20(%rsp)
1721         vpaddq  0x40($Tbl),@X[6],$t2
1722         vmovdqa $t3,0x30(%rsp)
1723         vpaddq  0x60($Tbl),@X[7],$t3
1724         vmovdqa $t0,0x40(%rsp)
1725         mov     $A,$a1
1726         vmovdqa $t1,0x50(%rsp)
1727         mov     $B,$a3
1728         vmovdqa $t2,0x60(%rsp)
1729         xor     $C,$a3                  # magic
1730         vmovdqa $t3,0x70(%rsp)
1731         mov     $E,$a0
1732         jmp     .Lavx_00_47
1733
1734 .align  16
1735 .Lavx_00_47:
1736         add     \$`16*2*$SZ`,$Tbl
1737 ___
1738 sub Xupdate_512_AVX () {
1739         (
1740         '&vpalignr      ($t0,@X[1],@X[0],$SZ)', # X[1..2]
1741          '&vpalignr     ($t3,@X[5],@X[4],$SZ)', # X[9..10]
1742         '&vpsrlq        ($t2,$t0,$sigma0[0])',
1743          '&vpaddq       (@X[0],@X[0],$t3);',    # X[0..1] += X[9..10]
1744         '&vpsrlq        ($t3,$t0,$sigma0[2])',
1745         '&vpsllq        ($t1,$t0,8*$SZ-$sigma0[1]);',
1746          '&vpxor        ($t0,$t3,$t2)',
1747         '&vpsrlq        ($t2,$t2,$sigma0[1]-$sigma0[0]);',
1748          '&vpxor        ($t0,$t0,$t1)',
1749         '&vpsllq        ($t1,$t1,$sigma0[1]-$sigma0[0]);',
1750          '&vpxor        ($t0,$t0,$t2)',
1751          '&vpsrlq       ($t3,@X[7],$sigma1[2]);',
1752         '&vpxor         ($t0,$t0,$t1)',         # sigma0(X[1..2])
1753          '&vpsllq       ($t2,@X[7],8*$SZ-$sigma1[1]);',
1754         '&vpaddq        (@X[0],@X[0],$t0)',     # X[0..1] += sigma0(X[1..2])
1755          '&vpsrlq       ($t1,@X[7],$sigma1[0]);',
1756          '&vpxor        ($t3,$t3,$t2)',
1757          '&vpsllq       ($t2,$t2,$sigma1[1]-$sigma1[0]);',
1758          '&vpxor        ($t3,$t3,$t1)',
1759          '&vpsrlq       ($t1,$t1,$sigma1[1]-$sigma1[0]);',
1760          '&vpxor        ($t3,$t3,$t2)',
1761          '&vpxor        ($t3,$t3,$t1)',         # sigma1(X[14..15])
1762         '&vpaddq        (@X[0],@X[0],$t3)',     # X[0..1] += sigma1(X[14..15])
1763         );
1764 }
1765
1766 sub AVX_512_00_47 () {
1767 my $j = shift;
1768 my $body = shift;
1769 my @X = @_;
1770 my @insns = (&$body,&$body);                    # 52 instructions
1771
1772         foreach (Xupdate_512_AVX()) {           # 23 instructions
1773             eval;
1774             eval(shift(@insns));
1775             eval(shift(@insns));
1776         }
1777         &vpaddq         ($t2,@X[0],16*2*$j-0x80."($Tbl)");
1778           foreach (@insns) { eval; }            # remaining instructions
1779         &vmovdqa        (16*$j."(%rsp)",$t2);
1780 }
1781
1782     for ($i=0,$j=0; $j<8; $j++) {
1783         &AVX_512_00_47($j,\&body_00_15,@X);
1784         push(@X,shift(@X));                     # rotate(@X)
1785     }
1786         &cmpb   ($SZ-1+16*2*$SZ-0x80."($Tbl)",0);
1787         &jne    (".Lavx_00_47");
1788
1789     for ($i=0; $i<16; ) {
1790         foreach(body_00_15()) { eval; }
1791     }
1792 }
1793 $code.=<<___;
1794         mov     $_ctx,$ctx
1795         mov     $a1,$A
1796
1797         add     $SZ*0($ctx),$A
1798         lea     16*$SZ($inp),$inp
1799         add     $SZ*1($ctx),$B
1800         add     $SZ*2($ctx),$C
1801         add     $SZ*3($ctx),$D
1802         add     $SZ*4($ctx),$E
1803         add     $SZ*5($ctx),$F
1804         add     $SZ*6($ctx),$G
1805         add     $SZ*7($ctx),$H
1806
1807         cmp     $_end,$inp
1808
1809         mov     $A,$SZ*0($ctx)
1810         mov     $B,$SZ*1($ctx)
1811         mov     $C,$SZ*2($ctx)
1812         mov     $D,$SZ*3($ctx)
1813         mov     $E,$SZ*4($ctx)
1814         mov     $F,$SZ*5($ctx)
1815         mov     $G,$SZ*6($ctx)
1816         mov     $H,$SZ*7($ctx)
1817         jb      .Lloop_avx
1818
1819         mov     $_rsp,%rsi
1820 .cfi_def_cfa    %rsi,8
1821         vzeroupper
1822 ___
1823 $code.=<<___ if ($win64);
1824         movaps  16*$SZ+32(%rsp),%xmm6
1825         movaps  16*$SZ+48(%rsp),%xmm7
1826         movaps  16*$SZ+64(%rsp),%xmm8
1827         movaps  16*$SZ+80(%rsp),%xmm9
1828 ___
1829 $code.=<<___ if ($win64 && $SZ>4);
1830         movaps  16*$SZ+96(%rsp),%xmm10
1831         movaps  16*$SZ+112(%rsp),%xmm11
1832 ___
1833 $code.=<<___;
1834         mov     -48(%rsi),%r15
1835 .cfi_restore    %r15
1836         mov     -40(%rsi),%r14
1837 .cfi_restore    %r14
1838         mov     -32(%rsi),%r13
1839 .cfi_restore    %r13
1840         mov     -24(%rsi),%r12
1841 .cfi_restore    %r12
1842         mov     -16(%rsi),%rbp
1843 .cfi_restore    %rbp
1844         mov     -8(%rsi),%rbx
1845 .cfi_restore    %rbx
1846         lea     (%rsi),%rsp
1847 .cfi_def_cfa_register   %rsp
1848 .Lepilogue_avx:
1849         ret
1850 .cfi_endproc
1851 .size   ${func}_avx,.-${func}_avx
1852 ___
1853
1854 if ($avx>1) {{
1855 ######################################################################
1856 # AVX2+BMI code path
1857 #
1858 my $a5=$SZ==4?"%esi":"%rsi";    # zap $inp
1859 my $PUSH8=8*2*$SZ;
1860 use integer;
1861
1862 sub bodyx_00_15 () {
1863         # at start $a1 should be zero, $a3 - $b^$c and $a4 copy of $f
1864         (
1865         '($a,$b,$c,$d,$e,$f,$g,$h)=@ROT;'.
1866
1867         '&add   ($h,(32*($i/(16/$SZ))+$SZ*($i%(16/$SZ)))%$PUSH8.$base)',    # h+=X[i]+K[i]
1868         '&and   ($a4,$e)',              # f&e
1869         '&rorx  ($a0,$e,$Sigma1[2])',
1870         '&rorx  ($a2,$e,$Sigma1[1])',
1871
1872         '&lea   ($a,"($a,$a1)")',       # h+=Sigma0(a) from the past
1873         '&lea   ($h,"($h,$a4)")',
1874         '&andn  ($a4,$e,$g)',           # ~e&g
1875         '&xor   ($a0,$a2)',
1876
1877         '&rorx  ($a1,$e,$Sigma1[0])',
1878         '&lea   ($h,"($h,$a4)")',       # h+=Ch(e,f,g)=(e&f)+(~e&g)
1879         '&xor   ($a0,$a1)',             # Sigma1(e)
1880         '&mov   ($a2,$a)',
1881
1882         '&rorx  ($a4,$a,$Sigma0[2])',
1883         '&lea   ($h,"($h,$a0)")',       # h+=Sigma1(e)
1884         '&xor   ($a2,$b)',              # a^b, b^c in next round
1885         '&rorx  ($a1,$a,$Sigma0[1])',
1886
1887         '&rorx  ($a0,$a,$Sigma0[0])',
1888         '&lea   ($d,"($d,$h)")',        # d+=h
1889         '&and   ($a3,$a2)',             # (b^c)&(a^b)
1890         '&xor   ($a1,$a4)',
1891
1892         '&xor   ($a3,$b)',              # Maj(a,b,c)=Ch(a^b,c,b)
1893         '&xor   ($a1,$a0)',             # Sigma0(a)
1894         '&lea   ($h,"($h,$a3)");'.      # h+=Maj(a,b,c)
1895         '&mov   ($a4,$e)',              # copy of f in future
1896
1897         '($a2,$a3) = ($a3,$a2); unshift(@ROT,pop(@ROT)); $i++;'
1898         );
1899         # and at the finish one has to $a+=$a1
1900 }
1901
1902 $code.=<<___;
1903 .type   ${func}_avx2,\@function,3
1904 .align  64
1905 ${func}_avx2:
1906 .cfi_startproc
1907 .Lavx2_shortcut:
1908         mov     %rsp,%rax               # copy %rsp
1909 .cfi_def_cfa_register   %rax
1910         push    %rbx
1911 .cfi_push       %rbx
1912         push    %rbp
1913 .cfi_push       %rbp
1914         push    %r12
1915 .cfi_push       %r12
1916         push    %r13
1917 .cfi_push       %r13
1918         push    %r14
1919 .cfi_push       %r14
1920         push    %r15
1921 .cfi_push       %r15
1922         sub     \$`2*$SZ*$rounds+4*8+$win64*16*($SZ==4?4:6)`,%rsp
1923         shl     \$4,%rdx                # num*16
1924         and     \$-256*$SZ,%rsp         # align stack frame
1925         lea     ($inp,%rdx,$SZ),%rdx    # inp+num*16*$SZ
1926         add     \$`2*$SZ*($rounds-8)`,%rsp
1927         mov     $ctx,$_ctx              # save ctx, 1st arg
1928         mov     $inp,$_inp              # save inp, 2nd arh
1929         mov     %rdx,$_end              # save end pointer, "3rd" arg
1930         mov     %rax,$_rsp              # save copy of %rsp
1931 .cfi_cfa_expression     $_rsp,deref,+8
1932 ___
1933 $code.=<<___ if ($win64);
1934         movaps  %xmm6,16*$SZ+32(%rsp)
1935         movaps  %xmm7,16*$SZ+48(%rsp)
1936         movaps  %xmm8,16*$SZ+64(%rsp)
1937         movaps  %xmm9,16*$SZ+80(%rsp)
1938 ___
1939 $code.=<<___ if ($win64 && $SZ>4);
1940         movaps  %xmm10,16*$SZ+96(%rsp)
1941         movaps  %xmm11,16*$SZ+112(%rsp)
1942 ___
1943 $code.=<<___;
1944 .Lprologue_avx2:
1945
1946         vzeroupper
1947         sub     \$-16*$SZ,$inp          # inp++, size optimization
1948         mov     $SZ*0($ctx),$A
1949         mov     $inp,%r12               # borrow $T1
1950         mov     $SZ*1($ctx),$B
1951         cmp     %rdx,$inp               # $_end
1952         mov     $SZ*2($ctx),$C
1953         cmove   %rsp,%r12               # next block or random data
1954         mov     $SZ*3($ctx),$D
1955         mov     $SZ*4($ctx),$E
1956         mov     $SZ*5($ctx),$F
1957         mov     $SZ*6($ctx),$G
1958         mov     $SZ*7($ctx),$H
1959 ___
1960                                         if ($SZ==4) {   # SHA256
1961     my @X = map("%ymm$_",(0..3));
1962     my ($t0,$t1,$t2,$t3, $t4,$t5) = map("%ymm$_",(4..9));
1963
1964 $code.=<<___;
1965         vmovdqa $TABLE+`$SZ*2*$rounds`+32(%rip),$t4
1966         vmovdqa $TABLE+`$SZ*2*$rounds`+64(%rip),$t5
1967         jmp     .Loop_avx2
1968 .align  16
1969 .Loop_avx2:
1970         vmovdqa $TABLE+`$SZ*2*$rounds`(%rip),$t3
1971         vmovdqu -16*$SZ+0($inp),%xmm0
1972         vmovdqu -16*$SZ+16($inp),%xmm1
1973         vmovdqu -16*$SZ+32($inp),%xmm2
1974         vmovdqu -16*$SZ+48($inp),%xmm3
1975         #mov            $inp,$_inp      # offload $inp
1976         vinserti128     \$1,(%r12),@X[0],@X[0]
1977         vinserti128     \$1,16(%r12),@X[1],@X[1]
1978         vpshufb         $t3,@X[0],@X[0]
1979         vinserti128     \$1,32(%r12),@X[2],@X[2]
1980         vpshufb         $t3,@X[1],@X[1]
1981         vinserti128     \$1,48(%r12),@X[3],@X[3]
1982
1983         lea     $TABLE(%rip),$Tbl
1984         vpshufb $t3,@X[2],@X[2]
1985         vpaddd  0x00($Tbl),@X[0],$t0
1986         vpshufb $t3,@X[3],@X[3]
1987         vpaddd  0x20($Tbl),@X[1],$t1
1988         vpaddd  0x40($Tbl),@X[2],$t2
1989         vpaddd  0x60($Tbl),@X[3],$t3
1990         vmovdqa $t0,0x00(%rsp)
1991         xor     $a1,$a1
1992         vmovdqa $t1,0x20(%rsp)
1993         lea     -$PUSH8(%rsp),%rsp
1994         mov     $B,$a3
1995         vmovdqa $t2,0x00(%rsp)
1996         xor     $C,$a3                  # magic
1997         vmovdqa $t3,0x20(%rsp)
1998         mov     $F,$a4
1999         sub     \$-16*2*$SZ,$Tbl        # size optimization
2000         jmp     .Lavx2_00_47
2001
2002 .align  16
2003 .Lavx2_00_47:
2004 ___
2005
2006 sub AVX2_256_00_47 () {
2007 my $j = shift;
2008 my $body = shift;
2009 my @X = @_;
2010 my @insns = (&$body,&$body,&$body,&$body);      # 96 instructions
2011 my $base = "+2*$PUSH8(%rsp)";
2012
2013         &lea    ("%rsp","-$PUSH8(%rsp)")        if (($j%2)==0);
2014         foreach (Xupdate_256_AVX()) {           # 29 instructions
2015             eval;
2016             eval(shift(@insns));
2017             eval(shift(@insns));
2018             eval(shift(@insns));
2019         }
2020         &vpaddd         ($t2,@X[0],16*2*$j."($Tbl)");
2021           foreach (@insns) { eval; }            # remaining instructions
2022         &vmovdqa        ((32*$j)%$PUSH8."(%rsp)",$t2);
2023 }
2024
2025     for ($i=0,$j=0; $j<4; $j++) {
2026         &AVX2_256_00_47($j,\&bodyx_00_15,@X);
2027         push(@X,shift(@X));                     # rotate(@X)
2028     }
2029         &lea    ($Tbl,16*2*$SZ."($Tbl)");
2030         &cmpb   (($SZ-1)."($Tbl)",0);
2031         &jne    (".Lavx2_00_47");
2032
2033     for ($i=0; $i<16; ) {
2034         my $base=$i<8?"+$PUSH8(%rsp)":"(%rsp)";
2035         foreach(bodyx_00_15()) { eval; }
2036     }
2037                                         } else {        # SHA512
2038     my @X = map("%ymm$_",(0..7));
2039     my ($t0,$t1,$t2,$t3) = map("%ymm$_",(8..11));
2040
2041 $code.=<<___;
2042         jmp     .Loop_avx2
2043 .align  16
2044 .Loop_avx2:
2045         vmovdqu -16*$SZ($inp),%xmm0
2046         vmovdqu -16*$SZ+16($inp),%xmm1
2047         vmovdqu -16*$SZ+32($inp),%xmm2
2048         lea     $TABLE+0x80(%rip),$Tbl  # size optimization
2049         vmovdqu -16*$SZ+48($inp),%xmm3
2050         vmovdqu -16*$SZ+64($inp),%xmm4
2051         vmovdqu -16*$SZ+80($inp),%xmm5
2052         vmovdqu -16*$SZ+96($inp),%xmm6
2053         vmovdqu -16*$SZ+112($inp),%xmm7
2054         #mov    $inp,$_inp      # offload $inp
2055         vmovdqa `$SZ*2*$rounds-0x80`($Tbl),$t2
2056         vinserti128     \$1,(%r12),@X[0],@X[0]
2057         vinserti128     \$1,16(%r12),@X[1],@X[1]
2058          vpshufb        $t2,@X[0],@X[0]
2059         vinserti128     \$1,32(%r12),@X[2],@X[2]
2060          vpshufb        $t2,@X[1],@X[1]
2061         vinserti128     \$1,48(%r12),@X[3],@X[3]
2062          vpshufb        $t2,@X[2],@X[2]
2063         vinserti128     \$1,64(%r12),@X[4],@X[4]
2064          vpshufb        $t2,@X[3],@X[3]
2065         vinserti128     \$1,80(%r12),@X[5],@X[5]
2066          vpshufb        $t2,@X[4],@X[4]
2067         vinserti128     \$1,96(%r12),@X[6],@X[6]
2068          vpshufb        $t2,@X[5],@X[5]
2069         vinserti128     \$1,112(%r12),@X[7],@X[7]
2070
2071         vpaddq  -0x80($Tbl),@X[0],$t0
2072         vpshufb $t2,@X[6],@X[6]
2073         vpaddq  -0x60($Tbl),@X[1],$t1
2074         vpshufb $t2,@X[7],@X[7]
2075         vpaddq  -0x40($Tbl),@X[2],$t2
2076         vpaddq  -0x20($Tbl),@X[3],$t3
2077         vmovdqa $t0,0x00(%rsp)
2078         vpaddq  0x00($Tbl),@X[4],$t0
2079         vmovdqa $t1,0x20(%rsp)
2080         vpaddq  0x20($Tbl),@X[5],$t1
2081         vmovdqa $t2,0x40(%rsp)
2082         vpaddq  0x40($Tbl),@X[6],$t2
2083         vmovdqa $t3,0x60(%rsp)
2084         lea     -$PUSH8(%rsp),%rsp
2085         vpaddq  0x60($Tbl),@X[7],$t3
2086         vmovdqa $t0,0x00(%rsp)
2087         xor     $a1,$a1
2088         vmovdqa $t1,0x20(%rsp)
2089         mov     $B,$a3
2090         vmovdqa $t2,0x40(%rsp)
2091         xor     $C,$a3                  # magic
2092         vmovdqa $t3,0x60(%rsp)
2093         mov     $F,$a4
2094         add     \$16*2*$SZ,$Tbl
2095         jmp     .Lavx2_00_47
2096
2097 .align  16
2098 .Lavx2_00_47:
2099 ___
2100
2101 sub AVX2_512_00_47 () {
2102 my $j = shift;
2103 my $body = shift;
2104 my @X = @_;
2105 my @insns = (&$body,&$body);                    # 48 instructions
2106 my $base = "+2*$PUSH8(%rsp)";
2107
2108         &lea    ("%rsp","-$PUSH8(%rsp)")        if (($j%4)==0);
2109         foreach (Xupdate_512_AVX()) {           # 23 instructions
2110             eval;
2111             if ($_ !~ /\;$/) {
2112                 eval(shift(@insns));
2113                 eval(shift(@insns));
2114                 eval(shift(@insns));
2115             }
2116         }
2117         &vpaddq         ($t2,@X[0],16*2*$j-0x80."($Tbl)");
2118           foreach (@insns) { eval; }            # remaining instructions
2119         &vmovdqa        ((32*$j)%$PUSH8."(%rsp)",$t2);
2120 }
2121
2122     for ($i=0,$j=0; $j<8; $j++) {
2123         &AVX2_512_00_47($j,\&bodyx_00_15,@X);
2124         push(@X,shift(@X));                     # rotate(@X)
2125     }
2126         &lea    ($Tbl,16*2*$SZ."($Tbl)");
2127         &cmpb   (($SZ-1-0x80)."($Tbl)",0);
2128         &jne    (".Lavx2_00_47");
2129
2130     for ($i=0; $i<16; ) {
2131         my $base=$i<8?"+$PUSH8(%rsp)":"(%rsp)";
2132         foreach(bodyx_00_15()) { eval; }
2133     }
2134 }
2135 $code.=<<___;
2136         mov     `2*$SZ*$rounds`(%rsp),$ctx      # $_ctx
2137         add     $a1,$A
2138         #mov    `2*$SZ*$rounds+8`(%rsp),$inp    # $_inp
2139         lea     `2*$SZ*($rounds-8)`(%rsp),$Tbl
2140
2141         add     $SZ*0($ctx),$A
2142         add     $SZ*1($ctx),$B
2143         add     $SZ*2($ctx),$C
2144         add     $SZ*3($ctx),$D
2145         add     $SZ*4($ctx),$E
2146         add     $SZ*5($ctx),$F
2147         add     $SZ*6($ctx),$G
2148         add     $SZ*7($ctx),$H
2149
2150         mov     $A,$SZ*0($ctx)
2151         mov     $B,$SZ*1($ctx)
2152         mov     $C,$SZ*2($ctx)
2153         mov     $D,$SZ*3($ctx)
2154         mov     $E,$SZ*4($ctx)
2155         mov     $F,$SZ*5($ctx)
2156         mov     $G,$SZ*6($ctx)
2157         mov     $H,$SZ*7($ctx)
2158
2159         cmp     `$PUSH8+2*8`($Tbl),$inp # $_end
2160         je      .Ldone_avx2
2161
2162         xor     $a1,$a1
2163         mov     $B,$a3
2164         xor     $C,$a3                  # magic
2165         mov     $F,$a4
2166         jmp     .Lower_avx2
2167 .align  16
2168 .Lower_avx2:
2169 ___
2170     for ($i=0; $i<8; ) {
2171         my $base="+16($Tbl)";
2172         foreach(bodyx_00_15()) { eval; }
2173     }
2174 $code.=<<___;
2175         lea     -$PUSH8($Tbl),$Tbl
2176         cmp     %rsp,$Tbl
2177         jae     .Lower_avx2
2178
2179         mov     `2*$SZ*$rounds`(%rsp),$ctx      # $_ctx
2180         add     $a1,$A
2181         #mov    `2*$SZ*$rounds+8`(%rsp),$inp    # $_inp
2182         lea     `2*$SZ*($rounds-8)`(%rsp),%rsp
2183
2184         add     $SZ*0($ctx),$A
2185         add     $SZ*1($ctx),$B
2186         add     $SZ*2($ctx),$C
2187         add     $SZ*3($ctx),$D
2188         add     $SZ*4($ctx),$E
2189         add     $SZ*5($ctx),$F
2190         lea     `2*16*$SZ`($inp),$inp   # inp+=2
2191         add     $SZ*6($ctx),$G
2192         mov     $inp,%r12
2193         add     $SZ*7($ctx),$H
2194         cmp     $_end,$inp
2195
2196         mov     $A,$SZ*0($ctx)
2197         cmove   %rsp,%r12               # next block or stale data
2198         mov     $B,$SZ*1($ctx)
2199         mov     $C,$SZ*2($ctx)
2200         mov     $D,$SZ*3($ctx)
2201         mov     $E,$SZ*4($ctx)
2202         mov     $F,$SZ*5($ctx)
2203         mov     $G,$SZ*6($ctx)
2204         mov     $H,$SZ*7($ctx)
2205
2206         jbe     .Loop_avx2
2207         lea     (%rsp),$Tbl
2208
2209 .Ldone_avx2:
2210         lea     ($Tbl),%rsp
2211         mov     $_rsp,%rsi
2212 .cfi_def_cfa    %rsi,8
2213         vzeroupper
2214 ___
2215 $code.=<<___ if ($win64);
2216         movaps  16*$SZ+32(%rsp),%xmm6
2217         movaps  16*$SZ+48(%rsp),%xmm7
2218         movaps  16*$SZ+64(%rsp),%xmm8
2219         movaps  16*$SZ+80(%rsp),%xmm9
2220 ___
2221 $code.=<<___ if ($win64 && $SZ>4);
2222         movaps  16*$SZ+96(%rsp),%xmm10
2223         movaps  16*$SZ+112(%rsp),%xmm11
2224 ___
2225 $code.=<<___;
2226         mov     -48(%rsi),%r15
2227 .cfi_restore    %r15
2228         mov     -40(%rsi),%r14
2229 .cfi_restore    %r14
2230         mov     -32(%rsi),%r13
2231 .cfi_restore    %r13
2232         mov     -24(%rsi),%r12
2233 .cfi_restore    %r12
2234         mov     -16(%rsi),%rbp
2235 .cfi_restore    %rbp
2236         mov     -8(%rsi),%rbx
2237 .cfi_restore    %rbx
2238         lea     (%rsi),%rsp
2239 .cfi_def_cfa_register   %rsp
2240 .Lepilogue_avx2:
2241         ret
2242 .cfi_endproc
2243 .size   ${func}_avx2,.-${func}_avx2
2244 ___
2245 }}
2246 }}}}}
2247
2248 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
2249 #               CONTEXT *context,DISPATCHER_CONTEXT *disp)
2250 if ($win64) {
2251 $rec="%rcx";
2252 $frame="%rdx";
2253 $context="%r8";
2254 $disp="%r9";
2255
2256 $code.=<<___;
2257 .extern __imp_RtlVirtualUnwind
2258 .type   se_handler,\@abi-omnipotent
2259 .align  16
2260 se_handler:
2261         push    %rsi
2262         push    %rdi
2263         push    %rbx
2264         push    %rbp
2265         push    %r12
2266         push    %r13
2267         push    %r14
2268         push    %r15
2269         pushfq
2270         sub     \$64,%rsp
2271
2272         mov     120($context),%rax      # pull context->Rax
2273         mov     248($context),%rbx      # pull context->Rip
2274
2275         mov     8($disp),%rsi           # disp->ImageBase
2276         mov     56($disp),%r11          # disp->HanderlData
2277
2278         mov     0(%r11),%r10d           # HandlerData[0]
2279         lea     (%rsi,%r10),%r10        # prologue label
2280         cmp     %r10,%rbx               # context->Rip<prologue label
2281         jb      .Lin_prologue
2282
2283         mov     152($context),%rax      # pull context->Rsp
2284
2285         mov     4(%r11),%r10d           # HandlerData[1]
2286         lea     (%rsi,%r10),%r10        # epilogue label
2287         cmp     %r10,%rbx               # context->Rip>=epilogue label
2288         jae     .Lin_prologue
2289 ___
2290 $code.=<<___ if ($avx>1);
2291         lea     .Lavx2_shortcut(%rip),%r10
2292         cmp     %r10,%rbx               # context->Rip<avx2_shortcut
2293         jb      .Lnot_in_avx2
2294
2295         and     \$-256*$SZ,%rax
2296         add     \$`2*$SZ*($rounds-8)`,%rax
2297 .Lnot_in_avx2:
2298 ___
2299 $code.=<<___;
2300         mov     %rax,%rsi               # put aside Rsp
2301         mov     16*$SZ+3*8(%rax),%rax   # pull $_rsp
2302
2303         mov     -8(%rax),%rbx
2304         mov     -16(%rax),%rbp
2305         mov     -24(%rax),%r12
2306         mov     -32(%rax),%r13
2307         mov     -40(%rax),%r14
2308         mov     -48(%rax),%r15
2309         mov     %rbx,144($context)      # restore context->Rbx
2310         mov     %rbp,160($context)      # restore context->Rbp
2311         mov     %r12,216($context)      # restore context->R12
2312         mov     %r13,224($context)      # restore context->R13
2313         mov     %r14,232($context)      # restore context->R14
2314         mov     %r15,240($context)      # restore context->R15
2315
2316         lea     .Lepilogue(%rip),%r10
2317         cmp     %r10,%rbx
2318         jb      .Lin_prologue           # non-AVX code
2319
2320         lea     16*$SZ+4*8(%rsi),%rsi   # Xmm6- save area
2321         lea     512($context),%rdi      # &context.Xmm6
2322         mov     \$`$SZ==4?8:12`,%ecx
2323         .long   0xa548f3fc              # cld; rep movsq
2324
2325 .Lin_prologue:
2326         mov     8(%rax),%rdi
2327         mov     16(%rax),%rsi
2328         mov     %rax,152($context)      # restore context->Rsp
2329         mov     %rsi,168($context)      # restore context->Rsi
2330         mov     %rdi,176($context)      # restore context->Rdi
2331
2332         mov     40($disp),%rdi          # disp->ContextRecord
2333         mov     $context,%rsi           # context
2334         mov     \$154,%ecx              # sizeof(CONTEXT)
2335         .long   0xa548f3fc              # cld; rep movsq
2336
2337         mov     $disp,%rsi
2338         xor     %rcx,%rcx               # arg1, UNW_FLAG_NHANDLER
2339         mov     8(%rsi),%rdx            # arg2, disp->ImageBase
2340         mov     0(%rsi),%r8             # arg3, disp->ControlPc
2341         mov     16(%rsi),%r9            # arg4, disp->FunctionEntry
2342         mov     40(%rsi),%r10           # disp->ContextRecord
2343         lea     56(%rsi),%r11           # &disp->HandlerData
2344         lea     24(%rsi),%r12           # &disp->EstablisherFrame
2345         mov     %r10,32(%rsp)           # arg5
2346         mov     %r11,40(%rsp)           # arg6
2347         mov     %r12,48(%rsp)           # arg7
2348         mov     %rcx,56(%rsp)           # arg8, (NULL)
2349         call    *__imp_RtlVirtualUnwind(%rip)
2350
2351         mov     \$1,%eax                # ExceptionContinueSearch
2352         add     \$64,%rsp
2353         popfq
2354         pop     %r15
2355         pop     %r14
2356         pop     %r13
2357         pop     %r12
2358         pop     %rbp
2359         pop     %rbx
2360         pop     %rdi
2361         pop     %rsi
2362         ret
2363 .size   se_handler,.-se_handler
2364 ___
2365
2366 $code.=<<___ if ($SZ==4 && $shaext);
2367 .type   shaext_handler,\@abi-omnipotent
2368 .align  16
2369 shaext_handler:
2370         push    %rsi
2371         push    %rdi
2372         push    %rbx
2373         push    %rbp
2374         push    %r12
2375         push    %r13
2376         push    %r14
2377         push    %r15
2378         pushfq
2379         sub     \$64,%rsp
2380
2381         mov     120($context),%rax      # pull context->Rax
2382         mov     248($context),%rbx      # pull context->Rip
2383
2384         lea     .Lprologue_shaext(%rip),%r10
2385         cmp     %r10,%rbx               # context->Rip<.Lprologue
2386         jb      .Lin_prologue
2387
2388         lea     .Lepilogue_shaext(%rip),%r10
2389         cmp     %r10,%rbx               # context->Rip>=.Lepilogue
2390         jae     .Lin_prologue
2391
2392         lea     -8-5*16(%rax),%rsi
2393         lea     512($context),%rdi      # &context.Xmm6
2394         mov     \$10,%ecx
2395         .long   0xa548f3fc              # cld; rep movsq
2396
2397         jmp     .Lin_prologue
2398 .size   shaext_handler,.-shaext_handler
2399 ___
2400
2401 $code.=<<___;
2402 .section        .pdata
2403 .align  4
2404         .rva    .LSEH_begin_$func
2405         .rva    .LSEH_end_$func
2406         .rva    .LSEH_info_$func
2407 ___
2408 $code.=<<___ if ($SZ==4 && $shaext);
2409         .rva    .LSEH_begin_${func}_shaext
2410         .rva    .LSEH_end_${func}_shaext
2411         .rva    .LSEH_info_${func}_shaext
2412 ___
2413 $code.=<<___ if ($SZ==4);
2414         .rva    .LSEH_begin_${func}_ssse3
2415         .rva    .LSEH_end_${func}_ssse3
2416         .rva    .LSEH_info_${func}_ssse3
2417 ___
2418 $code.=<<___ if ($avx && $SZ==8);
2419         .rva    .LSEH_begin_${func}_xop
2420         .rva    .LSEH_end_${func}_xop
2421         .rva    .LSEH_info_${func}_xop
2422 ___
2423 $code.=<<___ if ($avx);
2424         .rva    .LSEH_begin_${func}_avx
2425         .rva    .LSEH_end_${func}_avx
2426         .rva    .LSEH_info_${func}_avx
2427 ___
2428 $code.=<<___ if ($avx>1);
2429         .rva    .LSEH_begin_${func}_avx2
2430         .rva    .LSEH_end_${func}_avx2
2431         .rva    .LSEH_info_${func}_avx2
2432 ___
2433 $code.=<<___;
2434 .section        .xdata
2435 .align  8
2436 .LSEH_info_$func:
2437         .byte   9,0,0,0
2438         .rva    se_handler
2439         .rva    .Lprologue,.Lepilogue                   # HandlerData[]
2440 ___
2441 $code.=<<___ if ($SZ==4 && $shaext);
2442 .LSEH_info_${func}_shaext:
2443         .byte   9,0,0,0
2444         .rva    shaext_handler
2445 ___
2446 $code.=<<___ if ($SZ==4);
2447 .LSEH_info_${func}_ssse3:
2448         .byte   9,0,0,0
2449         .rva    se_handler
2450         .rva    .Lprologue_ssse3,.Lepilogue_ssse3       # HandlerData[]
2451 ___
2452 $code.=<<___ if ($avx && $SZ==8);
2453 .LSEH_info_${func}_xop:
2454         .byte   9,0,0,0
2455         .rva    se_handler
2456         .rva    .Lprologue_xop,.Lepilogue_xop           # HandlerData[]
2457 ___
2458 $code.=<<___ if ($avx);
2459 .LSEH_info_${func}_avx:
2460         .byte   9,0,0,0
2461         .rva    se_handler
2462         .rva    .Lprologue_avx,.Lepilogue_avx           # HandlerData[]
2463 ___
2464 $code.=<<___ if ($avx>1);
2465 .LSEH_info_${func}_avx2:
2466         .byte   9,0,0,0
2467         .rva    se_handler
2468         .rva    .Lprologue_avx2,.Lepilogue_avx2         # HandlerData[]
2469 ___
2470 }
2471
2472 sub sha256op38 {
2473     my $instr = shift;
2474     my %opcodelet = (
2475                 "sha256rnds2" => 0xcb,
2476                 "sha256msg1"  => 0xcc,
2477                 "sha256msg2"  => 0xcd   );
2478
2479     if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-7]),\s*%xmm([0-7])/) {
2480       my @opcode=(0x0f,0x38);
2481         push @opcode,$opcodelet{$instr};
2482         push @opcode,0xc0|($1&7)|(($2&7)<<3);           # ModR/M
2483         return ".byte\t".join(',',@opcode);
2484     } else {
2485         return $instr."\t".@_[0];
2486     }
2487 }
2488
2489 foreach (split("\n",$code)) {
2490         s/\`([^\`]*)\`/eval $1/geo;
2491
2492         s/\b(sha256[^\s]*)\s+(.*)/sha256op38($1,$2)/geo;
2493
2494         print $_,"\n";
2495 }
2496 close STDOUT;