5bed43b60cac292e1c0e9fee778d1b4c2ffd9f55
[openssl.git] / crypto / sha / asm / sha256-mb-x86_64.pl
1 #!/usr/bin/env perl
2
3 # ====================================================================
4 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
5 # project. The module is, however, dual licensed under OpenSSL and
6 # CRYPTOGAMS licenses depending on where you obtain it. For further
7 # details see http://www.openssl.org/~appro/cryptogams/.
8 # ====================================================================
9
10 # Multi-buffer SHA256 procedure processes n buffers in parallel by
11 # placing buffer data to designated lane of SIMD register. n is
12 # naturally limited to 4 on pre-AVX2 processors and to 8 on
13 # AVX2-capable processors such as Haswell.
14 #
15 #               this    +aesni(*)       sha256  aesni-sha256    gain
16 # -------------------------------------------------------------------
17 # Westmere(**)  23.3/n  +1.28=7.11(n=4) 12.3    +3.75=16.1      +126%
18 # Atom(**)      39.1/n  +3.93=13.7(n=4) 20.8    +5.69=26.5      +93%
19 # Sandy Bridge  (20.5   +5.15=25.7)/n   11.6    13.0            +103%
20 # Ivy Bridge    (20.4   +5.14=25.5)/n   10.3    11.6            +82%
21 # Haswell(***)  (21.0   +5.00=26.0)/n   7.80    8.79            +170%
22 # Bulldozer     (21.6   +5.76=27.4)/n   13.6    13.7            +100%
23 #
24 # (*)   multi-block CBC encrypt with 128-bit key;
25 # (**)  (HASH+AES)/n does not apply to Westmere for n>3 and Atom,
26 #       because of lower AES-NI instruction throughput, nor is there
27 #       AES-NI-SHA256 stitch for these processors;
28 # (***) "this" is for n=8, when we gather twice as much data, result
29 #       for n=4 is 20.3+4.44=24.7;
30
31 $flavour = shift;
32 $output  = shift;
33 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
34
35 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
36
37 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
38 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
39 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
40 die "can't locate x86_64-xlate.pl";
41
42 $avx=0;
43
44 if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
45                 =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
46         $avx = ($1>=2.19) + ($1>=2.22);
47 }
48
49 if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
50            `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
51         $avx = ($1>=2.09) + ($1>=2.10);
52 }
53
54 if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
55            `ml64 2>&1` =~ /Version ([0-9]+)\./) {
56         $avx = ($1>=10) + ($1>=11);
57 }
58
59 open OUT,"| \"$^X\" $xlate $flavour $output";
60 *STDOUT=*OUT;
61
62 # void sha256_multi_block (
63 #     struct {  unsigned int A[8];
64 #               unsigned int B[8];
65 #               unsigned int C[8];
66 #               unsigned int D[8];
67 #               unsigned int E[8];
68 #               unsigned int F[8];
69 #               unsigned int G[8];
70 #               unsigned int H[8];      } *ctx,
71 #     struct {  void *ptr; int blocks;  } inp[8],
72 #     int num);         /* 1 or 2 */
73 #
74 $ctx="%rdi";    # 1st arg
75 $inp="%rsi";    # 2nd arg
76 $num="%edx";    # 3rd arg
77 @ptr=map("%r$_",(8..11));
78 $Tbl="%rbp";
79
80 @V=($A,$B,$C,$D,$E,$F,$G,$H)=map("%xmm$_",(8..15));
81 ($t1,$t2,$t3,$axb,$bxc,$Xi,$Xn,$sigma)=map("%xmm$_",(0..7));
82
83 $REG_SZ=16;
84
85 sub Xi_off {
86 my $off = shift;
87
88     $off %= 16; $off *= $REG_SZ;
89     $off<256 ? "$off-128(%rax)" : "$off-256-128(%rbx)";
90 }
91
92 sub ROUND_00_15 {
93 my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_;
94
95 $code.=<<___ if ($i<15);
96         movd            `4*$i`(@ptr[0]),$Xi
97         movd            `4*$i`(@ptr[1]),$t1
98         movd            `4*$i`(@ptr[2]),$t2
99         movd            `4*$i`(@ptr[3]),$t3
100         punpckldq       $t2,$Xi
101         punpckldq       $t3,$t1
102         punpckldq       $t1,$Xi
103         pshufb          $Xn,$Xi
104 ___
105 $code.=<<___ if ($i==15);
106         movd            `4*$i`(@ptr[0]),$Xi
107          lea            `16*4`(@ptr[0]),@ptr[0]
108         movd            `4*$i`(@ptr[1]),$t1
109          lea            `16*4`(@ptr[1]),@ptr[1]
110         movd            `4*$i`(@ptr[2]),$t2
111          lea            `16*4`(@ptr[2]),@ptr[2]
112         movd            `4*$i`(@ptr[3]),$t3
113          lea            `16*4`(@ptr[3]),@ptr[3]
114         punpckldq       $t2,$Xi
115         punpckldq       $t3,$t1
116         punpckldq       $t1,$Xi
117         pshufb          $Xn,$Xi
118 ___
119 $code.=<<___;
120         movdqa  $e,$sigma
121         movdqa  $e,$t3
122         psrld   \$6,$sigma
123         movdqa  $e,$t2
124         pslld   \$7,$t3
125         movdqa  $Xi,`&Xi_off($i)`
126          paddd  $h,$Xi                          # Xi+=h
127
128         psrld   \$11,$t2
129         pxor    $t3,$sigma
130         pslld   \$21-7,$t3
131          paddd  `32*($i%8)-128`($Tbl),$Xi       # Xi+=K[round]
132         pxor    $t2,$sigma
133
134         psrld   \$25-11,$t2
135          movdqa $e,$t1
136         pxor    $t3,$sigma
137          movdqa $e,$axb                         # borrow $axb
138         pslld   \$26-21,$t3
139          pandn  $g,$t1
140          pand   $f,$axb
141         pxor    $t2,$sigma
142
143         movdqa  $a,$t2
144         pxor    $t3,$sigma                      # Sigma1(e)
145         movdqa  $a,$t3
146         psrld   \$2,$t2
147         paddd   $sigma,$Xi                      # Xi+=Sigma1(e)
148          pxor   $axb,$t1                        # Ch(e,f,g)
149          movdqa $b,$axb
150         movdqa  $a,$sigma
151         pslld   \$10,$t3
152          pxor   $a,$axb                         # a^b, b^c in next round
153
154         psrld   \$13,$sigma
155         pxor    $t3,$t2
156          paddd  $t1,$Xi                         # Xi+=Ch(e,f,g)
157         pslld   \$19-10,$t3
158          pand   $axb,$bxc
159         pxor    $sigma,$t2
160
161         psrld   \$22-13,$sigma
162         pxor    $t3,$t2
163          movdqa $b,$h
164         pslld   \$30-19,$t3
165         pxor    $t2,$sigma
166          pxor   $bxc,$h                         # h=Maj(a,b,c)=Ch(a^b,c,b)
167          paddd  $Xi,$d                          # d+=Xi
168         pxor    $t3,$sigma                      # Sigma0(a)
169
170         paddd   $Xi,$h                          # h+=Xi
171         paddd   $sigma,$h                       # h+=Sigma0(a)
172 ___
173 $code.=<<___ if (($i%8)==7);
174         lea     `32*8`($Tbl),$Tbl
175 ___
176         ($axb,$bxc)=($bxc,$axb);
177 }
178
179 sub ROUND_16_XX {
180 my $i=shift;
181
182 $code.=<<___;
183         movdqa  `&Xi_off($i+1)`,$Xn
184         paddd   `&Xi_off($i+9)`,$Xi             # Xi+=X[i+9]
185
186         movdqa  $Xn,$sigma
187         movdqa  $Xn,$t2
188         psrld   \$3,$sigma
189         movdqa  $Xn,$t3
190
191         psrld   \$7,$t2
192         movdqa  `&Xi_off($i+14)`,$t1
193         pslld   \$14,$t3
194         pxor    $t2,$sigma
195         psrld   \$18-7,$t2
196         movdqa  $t1,$axb                        # borrow $axb
197         pxor    $t3,$sigma
198         pslld   \$25-14,$t3
199         pxor    $t2,$sigma
200         psrld   \$10,$t1
201         movdqa  $axb,$t2
202
203         psrld   \$17,$axb
204         pxor    $t3,$sigma                      # sigma0(X[i+1])
205         pslld   \$13,$t2
206          paddd  $sigma,$Xi                      # Xi+=sigma0(e)
207         pxor    $axb,$t1
208         psrld   \$19-17,$axb
209         pxor    $t2,$t1
210         pslld   \$15-13,$t2
211         pxor    $axb,$t1
212         pxor    $t2,$t1                         # sigma0(X[i+14])
213         paddd   $t1,$Xi                         # Xi+=sigma1(X[i+14])
214 ___
215         &ROUND_00_15($i,@_);
216         ($Xi,$Xn)=($Xn,$Xi);
217 }
218
219 $code.=<<___;
220 .text
221
222 .extern OPENSSL_ia32cap_P
223
224 .globl  sha256_multi_block
225 .type   sha256_multi_block,\@function,3
226 .align  32
227 sha256_multi_block:
228 ___
229 $code.=<<___ if ($avx);
230         mov     OPENSSL_ia32cap_P+4(%rip),%rcx
231         test    \$`1<<28`,%ecx
232         jnz     _avx_shortcut
233 ___
234 $code.=<<___;
235         mov     %rsp,%rax
236         push    %rbx
237         push    %rbp
238 ___
239 $code.=<<___ if ($win64);
240         lea     -0xa8(%rsp),%rsp
241         movaps  %xmm6,(%rsp)
242         movaps  %xmm7,0x10(%rsp)
243         movaps  %xmm8,0x20(%rsp)
244         movaps  %xmm9,0x30(%rsp)
245         movaps  %xmm10,-0x78(%rax)
246         movaps  %xmm11,-0x68(%rax)
247         movaps  %xmm12,-0x58(%rax)
248         movaps  %xmm13,-0x48(%rax)
249         movaps  %xmm14,-0x38(%rax)
250         movaps  %xmm15,-0x28(%rax)
251 ___
252 $code.=<<___;
253         sub     \$`$REG_SZ*18`, %rsp
254         and     \$-256,%rsp
255         mov     %rax,`$REG_SZ*17`(%rsp)         # original %rsp
256         lea     K256+128(%rip),$Tbl
257         lea     `$REG_SZ*16`(%rsp),%rbx
258         lea     0x80($ctx),$ctx                 # size optimization
259
260 .Loop_grande:
261         mov     $num,`$REG_SZ*17+8`(%rsp)       # original $num
262         xor     $num,$num
263 ___
264 for($i=0;$i<4;$i++) {
265     $code.=<<___;
266         mov     `16*$i+0`($inp),@ptr[$i]        # input pointer
267         mov     `16*$i+8`($inp),%ecx            # number of blocks
268         cmp     $num,%ecx
269         cmovg   %ecx,$num                       # find maximum
270         test    %ecx,%ecx
271         mov     %ecx,`4*$i`(%rbx)               # initialize counters
272         cmovle  $Tbl,@ptr[$i]                   # cancel input
273 ___
274 }
275 $code.=<<___;
276         test    $num,$num
277         jz      .Ldone
278
279         movdqu  0x00-0x80($ctx),$A              # load context
280          lea    128(%rsp),%rax
281         movdqu  0x20-0x80($ctx),$B
282         movdqu  0x40-0x80($ctx),$C
283         movdqu  0x60-0x80($ctx),$D
284         movdqu  0x80-0x80($ctx),$E
285         movdqu  0xa0-0x80($ctx),$F
286         movdqu  0xc0-0x80($ctx),$G
287         movdqu  0xe0-0x80($ctx),$H
288         movdqu  .Lpbswap(%rip),$Xn
289         jmp     .Loop
290
291 .align  32
292 .Loop:
293         movdqa  $C,$bxc
294         pxor    $B,$bxc                         # magic seed
295 ___
296 for($i=0;$i<16;$i++)    { &ROUND_00_15($i,@V); unshift(@V,pop(@V)); }
297 $code.=<<___;
298         movdqu  `&Xi_off($i)`,$Xi
299         mov     \$3,%ecx
300         jmp     .Loop_16_xx
301 .align  32
302 .Loop_16_xx:
303 ___
304 for(;$i<32;$i++)        { &ROUND_16_XX($i,@V); unshift(@V,pop(@V)); }
305 $code.=<<___;
306         dec     %ecx
307         jnz     .Loop_16_xx
308
309         mov     \$1,%ecx
310         lea     K256+128(%rip),$Tbl
311
312         movdqa  (%rbx),$sigma                   # pull counters
313         cmp     4*0(%rbx),%ecx                  # examine counters
314         pxor    $t1,$t1
315         cmovge  $Tbl,@ptr[0]                    # cancel input
316         cmp     4*1(%rbx),%ecx
317         movdqa  $sigma,$Xn
318         cmovge  $Tbl,@ptr[1]
319         cmp     4*2(%rbx),%ecx
320         pcmpgtd $t1,$Xn                         # mask value
321         cmovge  $Tbl,@ptr[2]
322         cmp     4*3(%rbx),%ecx
323         paddd   $Xn,$sigma                      # counters--
324         cmovge  $Tbl,@ptr[3]
325
326         movdqu  0x00-0x80($ctx),$t1
327         pand    $Xn,$A
328         movdqu  0x20-0x80($ctx),$t2
329         pand    $Xn,$B
330         movdqu  0x40-0x80($ctx),$t3
331         pand    $Xn,$C
332         movdqu  0x60-0x80($ctx),$Xi
333         pand    $Xn,$D
334         paddd   $t1,$A
335         movdqu  0x80-0x80($ctx),$t1
336         pand    $Xn,$E
337         paddd   $t2,$B
338         movdqu  0xa0-0x80($ctx),$t2
339         pand    $Xn,$F
340         paddd   $t3,$C
341         movdqu  0xc0-0x80($ctx),$t3
342         pand    $Xn,$G
343         paddd   $Xi,$D
344         movdqu  0xe0-0x80($ctx),$Xi
345         pand    $Xn,$H
346         paddd   $t1,$E
347         paddd   $t2,$F
348         movdqu  $A,0x00-0x80($ctx)
349         paddd   $t3,$G
350         movdqu  $B,0x20-0x80($ctx)
351         paddd   $Xi,$H
352         movdqu  $C,0x40-0x80($ctx)
353         movdqu  $D,0x60-0x80($ctx)
354         movdqu  $E,0x80-0x80($ctx)
355         movdqu  $F,0xa0-0x80($ctx)
356         movdqu  $G,0xc0-0x80($ctx)
357         movdqu  $H,0xe0-0x80($ctx)
358
359         movdqa  $sigma,(%rbx)                   # save counters
360         movdqa  .Lpbswap(%rip),$Xn
361         dec     $num
362         jnz     .Loop
363
364         mov     `$REG_SZ*17+8`(%rsp),$num
365         lea     $REG_SZ($ctx),$ctx
366         lea     `16*$REG_SZ/4`($inp),$inp
367         dec     $num
368         jnz     .Loop_grande
369
370 .Ldone:
371         mov     `$REG_SZ*17`(%rsp),%rax         # orignal %rsp
372 ___
373 $code.=<<___ if ($win64);
374         movaps  -0xb8(%rax),%xmm6
375         movaps  -0xa8(%rax),%xmm7
376         movaps  -0x98(%rax),%xmm8
377         movaps  -0x88(%rax),%xmm9
378         movaps  -0x78(%rax),%xmm10
379         movaps  -0x68(%rax),%xmm11
380         movaps  -0x58(%rax),%xmm12
381         movaps  -0x48(%rax),%xmm13
382         movaps  -0x38(%rax),%xmm14
383         movaps  -0x28(%rax),%xmm15
384 ___
385 $code.=<<___;
386         mov     -16(%rax),%rbp
387         mov     -8(%rax),%rbx
388         lea     (%rax),%rsp
389         ret
390 .size   sha256_multi_block,.-sha256_multi_block
391 ___
392                                                 if ($avx) {{{
393 sub ROUND_00_15_avx {
394 my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_;
395
396 $code.=<<___ if ($i<15 && $REG_SZ==16);
397         vmovd           `4*$i`(@ptr[0]),$Xi
398         vmovd           `4*$i`(@ptr[1]),$t1
399         vpinsrd         \$1,`4*$i`(@ptr[2]),$Xi,$Xi
400         vpinsrd         \$1,`4*$i`(@ptr[3]),$t1,$t1
401         vpunpckldq      $t1,$Xi,$Xi
402         vpshufb         $Xn,$Xi,$Xi
403 ___
404 $code.=<<___ if ($i==15 && $REG_SZ==16);
405         vmovd           `4*$i`(@ptr[0]),$Xi
406          lea            `16*4`(@ptr[0]),@ptr[0]
407         vmovd           `4*$i`(@ptr[1]),$t1
408          lea            `16*4`(@ptr[1]),@ptr[1]
409         vpinsrd         \$1,`4*$i`(@ptr[2]),$Xi,$Xi
410          lea            `16*4`(@ptr[2]),@ptr[2]
411         vpinsrd         \$1,`4*$i`(@ptr[3]),$t1,$t1
412          lea            `16*4`(@ptr[3]),@ptr[3]
413         vpunpckldq      $t1,$Xi,$Xi
414         vpshufb         $Xn,$Xi,$Xi
415 ___
416 $code.=<<___ if ($i<15 && $REG_SZ==32);
417         vmovd           `4*$i`(@ptr[0]),$Xi
418         vmovd           `4*$i`(@ptr[4]),$t1
419         vmovd           `4*$i`(@ptr[1]),$t2
420         vmovd           `4*$i`(@ptr[5]),$t3
421         vpinsrd         \$1,`4*$i`(@ptr[2]),$Xi,$Xi
422         vpinsrd         \$1,`4*$i`(@ptr[6]),$t1,$t1
423         vpinsrd         \$1,`4*$i`(@ptr[3]),$t2,$t2
424         vpunpckldq      $t2,$Xi,$Xi
425         vpinsrd         \$1,`4*$i`(@ptr[7]),$t3,$t3
426         vpunpckldq      $t3,$t1,$t1
427         vinserti128     $t1,$Xi,$Xi
428         vpshufb         $Xn,$Xi,$Xi
429 ___
430 $code.=<<___ if ($i==15 && $REG_SZ==32);
431         vmovd           `4*$i`(@ptr[0]),$Xi
432          lea            `16*4`(@ptr[0]),@ptr[0]
433         vmovd           `4*$i`(@ptr[4]),$t1
434          lea            `16*4`(@ptr[4]),@ptr[4]
435         vmovd           `4*$i`(@ptr[1]),$t2
436          lea            `16*4`(@ptr[1]),@ptr[1]
437         vmovd           `4*$i`(@ptr[5]),$t3
438          lea            `16*4`(@ptr[5]),@ptr[5]
439         vpinsrd         \$1,`4*$i`(@ptr[2]),$Xi,$Xi
440          lea            `16*4`(@ptr[2]),@ptr[2]
441         vpinsrd         \$1,`4*$i`(@ptr[6]),$t1,$t1
442          lea            `16*4`(@ptr[6]),@ptr[6]
443         vpinsrd         \$1,`4*$i`(@ptr[3]),$t2,$t2
444          lea            `16*4`(@ptr[3]),@ptr[3]
445         vpunpckldq      $t2,$Xi,$Xi
446         vpinsrd         \$1,`4*$i`(@ptr[7]),$t3,$t3
447          lea            `16*4`(@ptr[7]),@ptr[7]
448         vpunpckldq      $t3,$t1,$t1
449         vinserti128     $t1,$Xi,$Xi
450         vpshufb         $Xn,$Xi,$Xi
451 ___
452 $code.=<<___;
453         vpsrld  \$6,$e,$sigma
454         vpslld  \$26,$e,$t3
455         vmovdqu $Xi,`&Xi_off($i)`
456          vpaddd $h,$Xi,$Xi                      # Xi+=h
457
458         vpsrld  \$11,$e,$t2
459         vpxor   $t3,$sigma,$sigma
460         vpslld  \$21,$e,$t3
461          vpaddd `32*($i%8)-128`($Tbl),$Xi,$Xi   # Xi+=K[round]
462         vpxor   $t2,$sigma,$sigma
463
464         vpsrld  \$25,$e,$t2
465         vpxor   $t3,$sigma,$sigma
466         vpslld  \$7,$e,$t3
467          vpandn $g,$e,$t1
468          vpand  $f,$e,$axb                      # borrow $axb
469         vpxor   $t2,$sigma,$sigma
470
471         vpsrld  \$2,$a,$h                       # borrow $h
472         vpxor   $t3,$sigma,$sigma               # Sigma1(e)
473         vpslld  \$30,$a,$t2
474          vpxor  $axb,$t1,$t1                    # Ch(e,f,g)
475          vpxor  $a,$b,$axb                      # a^b, b^c in next round
476         vpxor   $t2,$h,$h
477         vpaddd  $sigma,$Xi,$Xi                  # Xi+=Sigma1(e)
478
479         vpsrld  \$13,$a,$t2
480         vpslld  \$19,$a,$t3
481          vpaddd $t1,$Xi,$Xi                     # Xi+=Ch(e,f,g)
482          vpand  $axb,$bxc,$bxc
483         vpxor   $t2,$h,$sigma
484
485         vpsrld  \$22,$a,$t2
486         vpxor   $t3,$sigma,$sigma
487         vpslld  \$10,$a,$t3
488          vpxor  $bxc,$b,$h                      # h=Maj(a,b,c)=Ch(a^b,c,b)
489          vpaddd $Xi,$d,$d                       # d+=Xi
490         vpxor   $t2,$sigma,$sigma
491         vpxor   $t3,$sigma,$sigma               # Sigma0(a)
492
493         vpaddd  $Xi,$h,$h                       # h+=Xi
494         vpaddd  $sigma,$h,$h                    # h+=Sigma0(a)
495 ___
496 $code.=<<___ if (($i%8)==7);
497         add     \$`32*8`,$Tbl
498 ___
499         ($axb,$bxc)=($bxc,$axb);
500 }
501
502 sub ROUND_16_XX_avx {
503 my $i=shift;
504
505 $code.=<<___;
506         vmovdqu `&Xi_off($i+1)`,$Xn
507         vpaddd  `&Xi_off($i+9)`,$Xi,$Xi         # Xi+=X[i+9]
508
509         vpsrld  \$3,$Xn,$sigma
510         vpsrld  \$7,$Xn,$t2
511         vpslld  \$25,$Xn,$t3
512         vpxor   $t2,$sigma,$sigma
513         vpsrld  \$18,$Xn,$t2
514         vpxor   $t3,$sigma,$sigma
515         vpslld  \$14,$Xn,$t3
516         vmovdqu `&Xi_off($i+14)`,$t1
517         vpsrld  \$10,$t1,$axb                   # borrow $axb
518
519         vpxor   $t2,$sigma,$sigma
520         vpsrld  \$17,$t1,$t2
521         vpxor   $t3,$sigma,$sigma               # sigma0(X[i+1])
522         vpslld  \$15,$t1,$t3
523          vpaddd $sigma,$Xi,$Xi                  # Xi+=sigma0(e)
524         vpxor   $t2,$axb,$sigma
525         vpsrld  \$19,$t1,$t2
526         vpxor   $t3,$sigma,$sigma
527         vpslld  \$13,$t1,$t3
528         vpxor   $t2,$sigma,$sigma
529         vpxor   $t3,$sigma,$sigma               # sigma0(X[i+14])
530         vpaddd  $sigma,$Xi,$Xi                  # Xi+=sigma1(X[i+14])
531 ___
532         &ROUND_00_15_avx($i,@_);
533         ($Xi,$Xn)=($Xn,$Xi);
534 }
535
536 $code.=<<___;
537 .type   sha256_multi_block_avx,\@function,3
538 .align  32
539 sha256_multi_block_avx:
540 _avx_shortcut:
541 ___
542 $code.=<<___ if ($avx>1);
543         shr     \$32,%rcx
544         cmp     \$2,$num
545         jb      .Lavx
546         test    \$`1<<5`,%ecx
547         jnz     _avx2_shortcut
548         jmp     .Lavx
549 .align  32
550 .Lavx:
551 ___
552 $code.=<<___;
553         mov     %rsp,%rax
554         push    %rbx
555         push    %rbp
556 ___
557 $code.=<<___ if ($win64);
558         lea     -0xa8(%rsp),%rsp
559         movaps  %xmm6,(%rsp)
560         movaps  %xmm7,0x10(%rsp)
561         movaps  %xmm8,0x20(%rsp)
562         movaps  %xmm9,0x30(%rsp)
563         movaps  %xmm10,-0x78(%rax)
564         movaps  %xmm11,-0x68(%rax)
565         movaps  %xmm12,-0x58(%rax)
566         movaps  %xmm13,-0x48(%rax)
567         movaps  %xmm14,-0x38(%rax)
568         movaps  %xmm15,-0x28(%rax)
569 ___
570 $code.=<<___;
571         sub     \$`$REG_SZ*18`, %rsp
572         and     \$-256,%rsp
573         mov     %rax,`$REG_SZ*17`(%rsp)         # original %rsp
574         lea     K256+128(%rip),$Tbl
575         lea     `$REG_SZ*16`(%rsp),%rbx
576         lea     0x80($ctx),$ctx                 # size optimization
577
578 .Loop_grande_avx:
579         mov     $num,`$REG_SZ*17+8`(%rsp)       # original $num
580         xor     $num,$num
581 ___
582 for($i=0;$i<4;$i++) {
583     $code.=<<___;
584         mov     `16*$i+0`($inp),@ptr[$i]        # input pointer
585         mov     `16*$i+8`($inp),%ecx            # number of blocks
586         cmp     $num,%ecx
587         cmovg   %ecx,$num                       # find maximum
588         test    %ecx,%ecx
589         mov     %ecx,`4*$i`(%rbx)               # initialize counters
590         cmovle  $Tbl,@ptr[$i]                   # cancel input
591 ___
592 }
593 $code.=<<___;
594         test    $num,$num
595         jz      .Ldone_avx
596
597         vmovdqu 0x00-0x80($ctx),$A              # load context
598          lea    128(%rsp),%rax
599         vmovdqu 0x20-0x80($ctx),$B
600         vmovdqu 0x40-0x80($ctx),$C
601         vmovdqu 0x60-0x80($ctx),$D
602         vmovdqu 0x80-0x80($ctx),$E
603         vmovdqu 0xa0-0x80($ctx),$F
604         vmovdqu 0xc0-0x80($ctx),$G
605         vmovdqu 0xe0-0x80($ctx),$H
606         vmovdqu .Lpbswap(%rip),$Xn
607         jmp     .Loop_avx
608
609 .align  32
610 .Loop_avx:
611         vpxor   $B,$C,$bxc                      # magic seed
612 ___
613 for($i=0;$i<16;$i++)    { &ROUND_00_15_avx($i,@V); unshift(@V,pop(@V)); }
614 $code.=<<___;
615         vmovdqu `&Xi_off($i)`,$Xi
616         mov     \$3,%ecx
617         jmp     .Loop_16_xx_avx
618 .align  32
619 .Loop_16_xx_avx:
620 ___
621 for(;$i<32;$i++)        { &ROUND_16_XX_avx($i,@V); unshift(@V,pop(@V)); }
622 $code.=<<___;
623         dec     %ecx
624         jnz     .Loop_16_xx_avx
625
626         mov     \$1,%ecx
627         lea     K256+128(%rip),$Tbl
628 ___
629 for($i=0;$i<4;$i++) {
630     $code.=<<___;
631         cmp     `4*$i`(%rbx),%ecx               # examine counters
632         cmovge  $Tbl,@ptr[$i]                   # cancel input
633 ___
634 }
635 $code.=<<___;
636         vmovdqa (%rbx),$sigma                   # pull counters
637         vpxor   $t1,$t1,$t1
638         vmovdqa $sigma,$Xn
639         vpcmpgtd $t1,$Xn,$Xn                    # mask value
640         vpaddd  $Xn,$sigma,$sigma               # counters--
641
642         vmovdqu 0x00-0x80($ctx),$t1
643         vpand   $Xn,$A,$A
644         vmovdqu 0x20-0x80($ctx),$t2
645         vpand   $Xn,$B,$B
646         vmovdqu 0x40-0x80($ctx),$t3
647         vpand   $Xn,$C,$C
648         vmovdqu 0x60-0x80($ctx),$Xi
649         vpand   $Xn,$D,$D
650         vpaddd  $t1,$A,$A
651         vmovdqu 0x80-0x80($ctx),$t1
652         vpand   $Xn,$E,$E
653         vpaddd  $t2,$B,$B
654         vmovdqu 0xa0-0x80($ctx),$t2
655         vpand   $Xn,$F,$F
656         vpaddd  $t3,$C,$C
657         vmovdqu 0xc0-0x80($ctx),$t3
658         vpand   $Xn,$G,$G
659         vpaddd  $Xi,$D,$D
660         vmovdqu 0xe0-0x80($ctx),$Xi
661         vpand   $Xn,$H,$H
662         vpaddd  $t1,$E,$E
663         vpaddd  $t2,$F,$F
664         vmovdqu $A,0x00-0x80($ctx)
665         vpaddd  $t3,$G,$G
666         vmovdqu $B,0x20-0x80($ctx)
667         vpaddd  $Xi,$H,$H
668         vmovdqu $C,0x40-0x80($ctx)
669         vmovdqu $D,0x60-0x80($ctx)
670         vmovdqu $E,0x80-0x80($ctx)
671         vmovdqu $F,0xa0-0x80($ctx)
672         vmovdqu $G,0xc0-0x80($ctx)
673         vmovdqu $H,0xe0-0x80($ctx)
674
675         vmovdqu $sigma,(%rbx)                   # save counters
676         vmovdqu .Lpbswap(%rip),$Xn
677         dec     $num
678         jnz     .Loop_avx
679
680         mov     `$REG_SZ*17+8`(%rsp),$num
681         lea     $REG_SZ($ctx),$ctx
682         lea     `16*$REG_SZ/4`($inp),$inp
683         dec     $num
684         jnz     .Loop_grande_avx
685
686 .Ldone_avx:
687         mov     `$REG_SZ*17`(%rsp),%rax         # orignal %rsp
688         vzeroupper
689 ___
690 $code.=<<___ if ($win64);
691         movaps  -0xb8(%rax),%xmm6
692         movaps  -0xa8(%rax),%xmm7
693         movaps  -0x98(%rax),%xmm8
694         movaps  -0x88(%rax),%xmm9
695         movaps  -0x78(%rax),%xmm10
696         movaps  -0x68(%rax),%xmm11
697         movaps  -0x58(%rax),%xmm12
698         movaps  -0x48(%rax),%xmm13
699         movaps  -0x38(%rax),%xmm14
700         movaps  -0x28(%rax),%xmm15
701 ___
702 $code.=<<___;
703         mov     -16(%rax),%rbp
704         mov     -8(%rax),%rbx
705         lea     (%rax),%rsp
706         ret
707 .size   sha256_multi_block_avx,.-sha256_multi_block_avx
708 ___
709                                                 if ($avx>1) {
710 $code =~ s/\`([^\`]*)\`/eval $1/gem;
711
712 $REG_SZ=32;
713 @ptr=map("%r$_",(12..15,8..11));
714
715 @V=($A,$B,$C,$D,$E,$F,$G,$H)=map("%ymm$_",(8..15));
716 ($t1,$t2,$t3,$axb,$bxc,$Xi,$Xn,$sigma)=map("%ymm$_",(0..7));
717
718 $code.=<<___;
719 .type   sha256_multi_block_avx2,\@function,3
720 .align  32
721 sha256_multi_block_avx2:
722 _avx2_shortcut:
723         mov     %rsp,%rax
724         push    %rbx
725         push    %rbp
726         push    %r12
727         push    %r13
728         push    %r14
729         push    %r15
730 ___
731 $code.=<<___ if ($win64);
732         lea     -0xa8(%rsp),%rsp
733         movaps  %xmm6,(%rsp)
734         movaps  %xmm7,0x10(%rsp)
735         movaps  %xmm8,0x20(%rsp)
736         movaps  %xmm9,0x30(%rsp)
737         movaps  %xmm10,0x40(%rsp)
738         movaps  %xmm11,0x50(%rsp)
739         movaps  %xmm12,-0x78(%rax)
740         movaps  %xmm13,-0x68(%rax)
741         movaps  %xmm14,-0x58(%rax)
742         movaps  %xmm15,-0x48(%rax)
743 ___
744 $code.=<<___;
745         sub     \$`$REG_SZ*18`, %rsp
746         and     \$-256,%rsp
747         mov     %rax,`$REG_SZ*17`(%rsp)         # original %rsp
748         lea     K256+128(%rip),$Tbl
749         lea     0x80($ctx),$ctx                 # size optimization
750
751 .Loop_grande_avx2:
752         mov     $num,`$REG_SZ*17+8`(%rsp)       # original $num
753         xor     $num,$num
754         lea     `$REG_SZ*16`(%rsp),%rbx
755 ___
756 for($i=0;$i<8;$i++) {
757     $code.=<<___;
758         mov     `16*$i+0`($inp),@ptr[$i]        # input pointer
759         mov     `16*$i+8`($inp),%ecx            # number of blocks
760         cmp     $num,%ecx
761         cmovg   %ecx,$num                       # find maximum
762         test    %ecx,%ecx
763         mov     %ecx,`4*$i`(%rbx)               # initialize counters
764         cmovle  $Tbl,@ptr[$i]                   # cancel input
765 ___
766 }
767 $code.=<<___;
768         vmovdqu 0x00-0x80($ctx),$A              # load context
769          lea    128(%rsp),%rax
770         vmovdqu 0x20-0x80($ctx),$B
771          lea    256+128(%rsp),%rbx
772         vmovdqu 0x40-0x80($ctx),$C
773         vmovdqu 0x60-0x80($ctx),$D
774         vmovdqu 0x80-0x80($ctx),$E
775         vmovdqu 0xa0-0x80($ctx),$F
776         vmovdqu 0xc0-0x80($ctx),$G
777         vmovdqu 0xe0-0x80($ctx),$H
778         vmovdqu .Lpbswap(%rip),$Xn
779         jmp     .Loop_avx2
780
781 .align  32
782 .Loop_avx2:
783         vpxor   $B,$C,$bxc                      # magic seed
784 ___
785 for($i=0;$i<16;$i++)    { &ROUND_00_15_avx($i,@V); unshift(@V,pop(@V)); }
786 $code.=<<___;
787         vmovdqu `&Xi_off($i)`,$Xi
788         mov     \$3,%ecx
789         jmp     .Loop_16_xx_avx2
790 .align  32
791 .Loop_16_xx_avx2:
792 ___
793 for(;$i<32;$i++)        { &ROUND_16_XX_avx($i,@V); unshift(@V,pop(@V)); }
794 $code.=<<___;
795         dec     %ecx
796         jnz     .Loop_16_xx_avx2
797
798         mov     \$1,%ecx
799         lea     `$REG_SZ*16`(%rsp),%rbx
800         lea     K256+128(%rip),$Tbl
801 ___
802 for($i=0;$i<8;$i++) {
803     $code.=<<___;
804         cmp     `4*$i`(%rbx),%ecx               # examine counters
805         cmovge  $Tbl,@ptr[$i]                   # cancel input
806 ___
807 }
808 $code.=<<___;
809         vmovdqa (%rbx),$sigma                   # pull counters
810         vpxor   $t1,$t1,$t1
811         vmovdqa $sigma,$Xn
812         vpcmpgtd $t1,$Xn,$Xn                    # mask value
813         vpaddd  $Xn,$sigma,$sigma               # counters--
814
815         vmovdqu 0x00-0x80($ctx),$t1
816         vpand   $Xn,$A,$A
817         vmovdqu 0x20-0x80($ctx),$t2
818         vpand   $Xn,$B,$B
819         vmovdqu 0x40-0x80($ctx),$t3
820         vpand   $Xn,$C,$C
821         vmovdqu 0x60-0x80($ctx),$Xi
822         vpand   $Xn,$D,$D
823         vpaddd  $t1,$A,$A
824         vmovdqu 0x80-0x80($ctx),$t1
825         vpand   $Xn,$E,$E
826         vpaddd  $t2,$B,$B
827         vmovdqu 0xa0-0x80($ctx),$t2
828         vpand   $Xn,$F,$F
829         vpaddd  $t3,$C,$C
830         vmovdqu 0xc0-0x80($ctx),$t3
831         vpand   $Xn,$G,$G
832         vpaddd  $Xi,$D,$D
833         vmovdqu 0xe0-0x80($ctx),$Xi
834         vpand   $Xn,$H,$H
835         vpaddd  $t1,$E,$E
836         vpaddd  $t2,$F,$F
837         vmovdqu $A,0x00-0x80($ctx)
838         vpaddd  $t3,$G,$G
839         vmovdqu $B,0x20-0x80($ctx)
840         vpaddd  $Xi,$H,$H
841         vmovdqu $C,0x40-0x80($ctx)
842         vmovdqu $D,0x60-0x80($ctx)
843         vmovdqu $E,0x80-0x80($ctx)
844         vmovdqu $F,0xa0-0x80($ctx)
845         vmovdqu $G,0xc0-0x80($ctx)
846         vmovdqu $H,0xe0-0x80($ctx)
847
848         vmovdqu $sigma,(%rbx)                   # save counters
849         lea     256+128(%rsp),%rbx
850         vmovdqu .Lpbswap(%rip),$Xn
851         dec     $num
852         jnz     .Loop_avx2
853
854         #mov    `$REG_SZ*17+8`(%rsp),$num
855         #lea    $REG_SZ($ctx),$ctx
856         #lea    `16*$REG_SZ/4`($inp),$inp
857         #dec    $num
858         #jnz    .Loop_grande_avx2
859
860 .Ldone_avx2:
861         mov     `$REG_SZ*17`(%rsp),%rax         # orignal %rsp
862         vzeroupper
863 ___
864 $code.=<<___ if ($win64);
865         movaps  -0xd8(%rax),%xmm6
866         movaps  -0xc8(%rax),%xmm7
867         movaps  -0xb8(%rax),%xmm8
868         movaps  -0xa8(%rax),%xmm9
869         movaps  -0x98(%rax),%xmm10
870         movaps  -0x88(%rax),%xmm11
871         movaps  -0x78(%rax),%xmm12
872         movaps  -0x68(%rax),%xmm13
873         movaps  -0x58(%rax),%xmm14
874         movaps  -0x48(%rax),%xmm15
875 ___
876 $code.=<<___;
877         mov     -48(%rax),%r15
878         mov     -40(%rax),%r14
879         mov     -32(%rax),%r13
880         mov     -24(%rax),%r12
881         mov     -16(%rax),%rbp
882         mov     -8(%rax),%rbx
883         lea     (%rax),%rsp
884         ret
885 .size   sha256_multi_block_avx2,.-sha256_multi_block_avx2
886 ___
887                                         }       }}}
888 $code.=<<___;
889 .align  256
890 K256:
891 ___
892 sub TABLE {
893     foreach (@_) {
894         $code.=<<___;
895         .long   $_,$_,$_,$_
896         .long   $_,$_,$_,$_
897 ___
898     }
899 }
900 &TABLE( 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,
901         0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
902         0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,
903         0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
904         0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,
905         0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
906         0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,
907         0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
908         0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,
909         0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
910         0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,
911         0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
912         0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,
913         0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
914         0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,
915         0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 );
916 $code.=<<___;
917 .Lpbswap:
918         .long   0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f     # pbswap
919         .long   0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f     # pbswap
920 ___
921
922 foreach (split("\n",$code)) {
923         s/\`([^\`]*)\`/eval($1)/ge;
924
925         s/\b(vmov[dq])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go          or
926         s/\b(vmovdqu)\b(.+)%x%ymm([0-9]+)/$1$2%xmm$3/go         or
927         s/\b(vpinsr[qd])\b(.+)%ymm([0-9]+),%ymm([0-9]+)/$1$2%xmm$3,%xmm$4/go    or
928         s/\b(vpextr[qd])\b(.+)%ymm([0-9]+)/$1$2%xmm$3/go        or
929         s/\b(vinserti128)\b(\s+)%ymm/$1$2\$1,%xmm/go            or
930         s/\b(vpbroadcast[qd]\s+)%ymm([0-9]+)/$1%xmm$2/go;
931         print $_,"\n";
932 }
933
934 close STDOUT;