aes/asm/aesni-sha*-x86_64.pl: fix IV handling in SHAEXT paths.
[openssl.git] / crypto / aes / asm / aesni-sha1-x86_64.pl
1 #! /usr/bin/env perl
2 # Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the OpenSSL license (the "License").  You may not use
5 # this file except in compliance with the License.  You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
8
9 #
10 # ====================================================================
11 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
12 # project. The module is, however, dual licensed under OpenSSL and
13 # CRYPTOGAMS licenses depending on where you obtain it. For further
14 # details see http://www.openssl.org/~appro/cryptogams/.
15 # ====================================================================
16 #
17 # June 2011
18 #
19 # This is AESNI-CBC+SHA1 "stitch" implementation. The idea, as spelled
20 # in http://download.intel.com/design/intarch/papers/323686.pdf, is
21 # that since AESNI-CBC encrypt exhibit *very* low instruction-level
22 # parallelism, interleaving it with another algorithm would allow to
23 # utilize processor resources better and achieve better performance.
24 # SHA1 instruction sequences(*) are taken from sha1-x86_64.pl and
25 # AESNI code is weaved into it. Below are performance numbers in
26 # cycles per processed byte, less is better, for standalone AESNI-CBC
27 # encrypt, sum of the latter and standalone SHA1, and "stitched"
28 # subroutine:
29 #
30 #               AES-128-CBC     +SHA1           stitch      gain
31 # Westmere      3.77[+5.3]      9.07            6.55        +38%
32 # Sandy Bridge  5.05[+5.0(6.1)] 10.06(11.15)    5.98(7.05)  +68%(+58%)
33 # Ivy Bridge    5.05[+4.6]      9.65            5.54        +74%
34 # Haswell       4.43[+3.6(4.2)] 8.00(8.58)      4.55(5.21)  +75%(+65%)
35 # Skylake       2.63[+3.5(4.1)] 6.17(6.69)      4.23(4.44)  +46%(+51%)
36 # Bulldozer     5.77[+6.0]      11.72           6.37        +84%
37 #
38 #               AES-192-CBC
39 # Westmere      4.51            9.81            6.80        +44%
40 # Sandy Bridge  6.05            11.06(12.15)    6.11(7.19)  +81%(+69%)
41 # Ivy Bridge    6.05            10.65           6.07        +75%
42 # Haswell       5.29            8.86(9.44)      5.32(5.32)  +67%(+77%)
43 # Bulldozer     6.89            12.84           6.96        +84%
44 #
45 #               AES-256-CBC
46 # Westmere      5.25            10.55           7.21        +46%
47 # Sandy Bridge  7.05            12.06(13.15)    7.12(7.72)  +69%(+70%)
48 # Ivy Bridge    7.05            11.65           7.12        +64%
49 # Haswell       6.19            9.76(10.34)     6.21(6.25)  +57%(+65%)
50 # Skylake       3.62            7.16(7.68)      4.56(4.76)  +57%(+61$)
51 # Bulldozer     8.00            13.95           8.25        +69%
52 #
53 # (*)   There are two code paths: SSSE3 and AVX. See sha1-568.pl for
54 #       background information. Above numbers in parentheses are SSSE3
55 #       results collected on AVX-capable CPU, i.e. apply on OSes that
56 #       don't support AVX.
57 #
58 # Needless to mention that it makes no sense to implement "stitched"
59 # *decrypt* subroutine. Because *both* AESNI-CBC decrypt and SHA1
60 # fully utilize parallelism, so stitching would not give any gain
61 # anyway. Well, there might be some, e.g. because of better cache
62 # locality... For reference, here are performance results for
63 # standalone AESNI-CBC decrypt:
64 #
65 #               AES-128-CBC     AES-192-CBC     AES-256-CBC
66 # Westmere      1.25            1.50            1.75
67 # Sandy Bridge  0.74            0.91            1.09
68 # Ivy Bridge    0.74            0.90            1.11
69 # Haswell       0.63            0.76            0.88
70 # Bulldozer     0.70            0.85            0.99
71
72 # And indeed:
73 #
74 #               AES-256-CBC     +SHA1           stitch      gain
75 # Westmere      1.75            7.20            6.68        +7.8%
76 # Sandy Bridge  1.09            6.09(7.22)      5.82(6.95)  +4.6%(+3.9%)
77 # Ivy Bridge    1.11            5.70            5.45        +4.6%
78 # Haswell       0.88            4.45(5.00)      4.39(4.69)  +1.4%(*)(+6.6%)
79 # Bulldozer     0.99            6.95            5.95        +17%(**)
80 #
81 # (*)   Tiny improvement coefficient on Haswell is because we compare
82 #       AVX1 stitch to sum with AVX2 SHA1.
83 # (**)  Execution is fully dominated by integer code sequence and
84 #       SIMD still hardly shows [in single-process benchmark;-]
85
86 $flavour = shift;
87 $output  = shift;
88 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
89
90 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
91
92 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
93 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
94 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
95 die "can't locate x86_64-xlate.pl";
96
97 $avx=1 if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
98                 =~ /GNU assembler version ([2-9]\.[0-9]+)/ &&
99            $1>=2.19);
100 $avx=1 if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
101            `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/ &&
102            $1>=2.09);
103 $avx=1 if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
104            `ml64 2>&1` =~ /Version ([0-9]+)\./ &&
105            $1>=10);
106 $avx=1 if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/ && $2>=3.0);
107
108 $shaext=1;      ### set to zero if compiling for 1.0.1
109
110 $stitched_decrypt=0;
111
112 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
113 *STDOUT=*OUT;
114
115 # void aesni_cbc_sha1_enc(const void *inp,
116 #                       void *out,
117 #                       size_t length,
118 #                       const AES_KEY *key,
119 #                       unsigned char *iv,
120 #                       SHA_CTX *ctx,
121 #                       const void *in0);
122
123 $code.=<<___;
124 .text
125 .extern OPENSSL_ia32cap_P
126
127 .globl  aesni_cbc_sha1_enc
128 .type   aesni_cbc_sha1_enc,\@abi-omnipotent
129 .align  32
130 aesni_cbc_sha1_enc:
131         # caller should check for SSSE3 and AES-NI bits
132         mov     OPENSSL_ia32cap_P+0(%rip),%r10d
133         mov     OPENSSL_ia32cap_P+4(%rip),%r11
134 ___
135 $code.=<<___ if ($shaext);
136         bt      \$61,%r11               # check SHA bit
137         jc      aesni_cbc_sha1_enc_shaext
138 ___
139 $code.=<<___ if ($avx);
140         and     \$`1<<28`,%r11d         # mask AVX bit
141         and     \$`1<<30`,%r10d         # mask "Intel CPU" bit
142         or      %r11d,%r10d
143         cmp     \$`1<<28|1<<30`,%r10d
144         je      aesni_cbc_sha1_enc_avx
145 ___
146 $code.=<<___;
147         jmp     aesni_cbc_sha1_enc_ssse3
148         ret
149 .size   aesni_cbc_sha1_enc,.-aesni_cbc_sha1_enc
150 ___
151
152 my ($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10");
153
154 my $Xi=4;
155 my @X=map("%xmm$_",(4..7,0..3));
156 my @Tx=map("%xmm$_",(8..10));
157 my @V=($A,$B,$C,$D,$E)=("%eax","%ebx","%ecx","%edx","%ebp");    # size optimization
158 my @T=("%esi","%edi");
159 my $j=0; my $jj=0; my $r=0; my $sn=0; my $rx=0;
160 my $K_XX_XX="%r11";
161 my ($rndkey0,$iv,$in)=map("%xmm$_",(11..13));                   # for enc
162 my @rndkey=("%xmm14","%xmm15");                                 # for enc
163 my ($inout0,$inout1,$inout2,$inout3)=map("%xmm$_",(12..15));    # for dec
164
165 if (1) {        # reassign for Atom Silvermont
166     # The goal is to minimize amount of instructions with more than
167     # 3 prefix bytes. Or in more practical terms to keep AES-NI *and*
168     # SSSE3 instructions to upper half of the register bank.
169     @X=map("%xmm$_",(8..11,4..7));
170     @Tx=map("%xmm$_",(12,13,3));
171     ($iv,$in,$rndkey0)=map("%xmm$_",(2,14,15));
172     @rndkey=("%xmm0","%xmm1");
173 }
174
175 sub AUTOLOAD()          # thunk [simplified] 32-bit style perlasm
176 { my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
177   my $arg = pop;
178     $arg = "\$$arg" if ($arg*1 eq $arg);
179     $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
180 }
181
182 my $_rol=sub { &rol(@_) };
183 my $_ror=sub { &ror(@_) };
184
185 $code.=<<___;
186 .type   aesni_cbc_sha1_enc_ssse3,\@function,6
187 .align  32
188 aesni_cbc_sha1_enc_ssse3:
189 .cfi_startproc
190         mov     `($win64?56:8)`(%rsp),$inp      # load 7th argument
191         #shr    \$6,$len                        # debugging artefact
192         #jz     .Lepilogue_ssse3                # debugging artefact
193         push    %rbx
194 .cfi_push       %rbx
195         push    %rbp
196 .cfi_push       %rbp
197         push    %r12
198 .cfi_push       %r12
199         push    %r13
200 .cfi_push       %r13
201         push    %r14
202 .cfi_push       %r14
203         push    %r15
204 .cfi_push       %r15
205         lea     `-104-($win64?10*16:0)`(%rsp),%rsp
206 .cfi_adjust_cfa_offset  `104+($win64?10*16:0)`
207         #mov    $in0,$inp                       # debugging artefact
208         #lea    64(%rsp),$ctx                   # debugging artefact
209 ___
210 $code.=<<___ if ($win64);
211         movaps  %xmm6,96+0(%rsp)
212         movaps  %xmm7,96+16(%rsp)
213         movaps  %xmm8,96+32(%rsp)
214         movaps  %xmm9,96+48(%rsp)
215         movaps  %xmm10,96+64(%rsp)
216         movaps  %xmm11,96+80(%rsp)
217         movaps  %xmm12,96+96(%rsp)
218         movaps  %xmm13,96+112(%rsp)
219         movaps  %xmm14,96+128(%rsp)
220         movaps  %xmm15,96+144(%rsp)
221 .Lprologue_ssse3:
222 ___
223 $code.=<<___;
224         mov     $in0,%r12                       # reassign arguments
225         mov     $out,%r13
226         mov     $len,%r14
227         lea     112($key),%r15                  # size optimization
228         movdqu  ($ivp),$iv                      # load IV
229         mov     $ivp,88(%rsp)                   # save $ivp
230 ___
231 ($in0,$out,$len,$key)=map("%r$_",(12..15));     # reassign arguments
232 my $rounds="${ivp}d";
233 $code.=<<___;
234         shl     \$6,$len
235         sub     $in0,$out
236         mov     240-112($key),$rounds
237         add     $inp,$len               # end of input
238
239         lea     K_XX_XX(%rip),$K_XX_XX
240         mov     0($ctx),$A              # load context
241         mov     4($ctx),$B
242         mov     8($ctx),$C
243         mov     12($ctx),$D
244         mov     $B,@T[0]                # magic seed
245         mov     16($ctx),$E
246         mov     $C,@T[1]
247         xor     $D,@T[1]
248         and     @T[1],@T[0]
249
250         movdqa  64($K_XX_XX),@Tx[2]     # pbswap mask
251         movdqa  0($K_XX_XX),@Tx[1]      # K_00_19
252         movdqu  0($inp),@X[-4&7]        # load input to %xmm[0-3]
253         movdqu  16($inp),@X[-3&7]
254         movdqu  32($inp),@X[-2&7]
255         movdqu  48($inp),@X[-1&7]
256         pshufb  @Tx[2],@X[-4&7]         # byte swap
257         pshufb  @Tx[2],@X[-3&7]
258         pshufb  @Tx[2],@X[-2&7]
259         add     \$64,$inp
260         paddd   @Tx[1],@X[-4&7]         # add K_00_19
261         pshufb  @Tx[2],@X[-1&7]
262         paddd   @Tx[1],@X[-3&7]
263         paddd   @Tx[1],@X[-2&7]
264         movdqa  @X[-4&7],0(%rsp)        # X[]+K xfer to IALU
265         psubd   @Tx[1],@X[-4&7]         # restore X[]
266         movdqa  @X[-3&7],16(%rsp)
267         psubd   @Tx[1],@X[-3&7]
268         movdqa  @X[-2&7],32(%rsp)
269         psubd   @Tx[1],@X[-2&7]
270         movups  -112($key),$rndkey0     # $key[0]
271         movups  16-112($key),$rndkey[0] # forward reference
272         jmp     .Loop_ssse3
273 ___
274
275 my $aesenc=sub {
276   use integer;
277   my ($n,$k)=($r/10,$r%10);
278     if ($k==0) {
279       $code.=<<___;
280         movups          `16*$n`($in0),$in               # load input
281         xorps           $rndkey0,$in
282 ___
283       $code.=<<___ if ($n);
284         movups          $iv,`16*($n-1)`($out,$in0)      # write output
285 ___
286       $code.=<<___;
287         xorps           $in,$iv
288         movups          `32+16*$k-112`($key),$rndkey[1]
289         aesenc          $rndkey[0],$iv
290 ___
291     } elsif ($k==9) {
292       $sn++;
293       $code.=<<___;
294         cmp             \$11,$rounds
295         jb              .Laesenclast$sn
296         movups          `32+16*($k+0)-112`($key),$rndkey[1]
297         aesenc          $rndkey[0],$iv
298         movups          `32+16*($k+1)-112`($key),$rndkey[0]
299         aesenc          $rndkey[1],$iv
300         je              .Laesenclast$sn
301         movups          `32+16*($k+2)-112`($key),$rndkey[1]
302         aesenc          $rndkey[0],$iv
303         movups          `32+16*($k+3)-112`($key),$rndkey[0]
304         aesenc          $rndkey[1],$iv
305 .Laesenclast$sn:
306         aesenclast      $rndkey[0],$iv
307         movups          16-112($key),$rndkey[1]         # forward reference
308 ___
309     } else {
310       $code.=<<___;
311         movups          `32+16*$k-112`($key),$rndkey[1]
312         aesenc          $rndkey[0],$iv
313 ___
314     }
315     $r++;       unshift(@rndkey,pop(@rndkey));
316 };
317
318 sub Xupdate_ssse3_16_31()               # recall that $Xi starts wtih 4
319 { use integer;
320   my $body = shift;
321   my @insns = (&$body,&$body,&$body,&$body);    # 40 instructions
322   my ($a,$b,$c,$d,$e);
323
324          eval(shift(@insns));           # ror
325         &pshufd (@X[0],@X[-4&7],0xee);  # was &movdqa   (@X[0],@X[-3&7]);
326          eval(shift(@insns));
327         &movdqa (@Tx[0],@X[-1&7]);
328           &paddd        (@Tx[1],@X[-1&7]);
329          eval(shift(@insns));
330          eval(shift(@insns));
331
332         &punpcklqdq(@X[0],@X[-3&7]);    # compose "X[-14]" in "X[0]", was &palignr(@X[0],@X[-4&7],8);
333          eval(shift(@insns));
334          eval(shift(@insns));           # rol
335          eval(shift(@insns));
336         &psrldq (@Tx[0],4);             # "X[-3]", 3 dwords
337          eval(shift(@insns));
338          eval(shift(@insns));
339
340         &pxor   (@X[0],@X[-4&7]);       # "X[0]"^="X[-16]"
341          eval(shift(@insns));
342          eval(shift(@insns));           # ror
343         &pxor   (@Tx[0],@X[-2&7]);      # "X[-3]"^"X[-8]"
344          eval(shift(@insns));
345          eval(shift(@insns));
346          eval(shift(@insns));
347
348         &pxor   (@X[0],@Tx[0]);         # "X[0]"^="X[-3]"^"X[-8]"
349          eval(shift(@insns));
350          eval(shift(@insns));           # rol
351           &movdqa       (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
352          eval(shift(@insns));
353          eval(shift(@insns));
354
355         &movdqa (@Tx[2],@X[0]);
356          eval(shift(@insns));
357          eval(shift(@insns));
358          eval(shift(@insns));           # ror
359         &movdqa (@Tx[0],@X[0]);
360          eval(shift(@insns));
361
362         &pslldq (@Tx[2],12);            # "X[0]"<<96, extract one dword
363         &paddd  (@X[0],@X[0]);
364          eval(shift(@insns));
365          eval(shift(@insns));
366
367         &psrld  (@Tx[0],31);
368          eval(shift(@insns));
369          eval(shift(@insns));           # rol
370          eval(shift(@insns));
371         &movdqa (@Tx[1],@Tx[2]);
372          eval(shift(@insns));
373          eval(shift(@insns));
374
375         &psrld  (@Tx[2],30);
376          eval(shift(@insns));
377          eval(shift(@insns));           # ror
378         &por    (@X[0],@Tx[0]);         # "X[0]"<<<=1
379          eval(shift(@insns));
380          eval(shift(@insns));
381          eval(shift(@insns));
382
383         &pslld  (@Tx[1],2);
384         &pxor   (@X[0],@Tx[2]);
385          eval(shift(@insns));
386           &movdqa       (@Tx[2],eval(16*(($Xi)/5))."($K_XX_XX)");       # K_XX_XX
387          eval(shift(@insns));           # rol
388          eval(shift(@insns));
389          eval(shift(@insns));
390
391         &pxor   (@X[0],@Tx[1]);         # "X[0]"^=("X[0]">>96)<<<2
392         &pshufd (@Tx[1],@X[-1&7],0xee)  if ($Xi==7);    # was &movdqa   (@Tx[0],@X[-1&7]) in Xupdate_ssse3_32_79
393
394          foreach (@insns) { eval; }     # remaining instructions [if any]
395
396   $Xi++;        push(@X,shift(@X));     # "rotate" X[]
397                 push(@Tx,shift(@Tx));
398 }
399
400 sub Xupdate_ssse3_32_79()
401 { use integer;
402   my $body = shift;
403   my @insns = (&$body,&$body,&$body,&$body);    # 32 to 44 instructions
404   my ($a,$b,$c,$d,$e);
405
406          eval(shift(@insns))            if ($Xi==8);
407         &pxor   (@X[0],@X[-4&7]);       # "X[0]"="X[-32]"^"X[-16]"
408          eval(shift(@insns))            if ($Xi==8);
409          eval(shift(@insns));           # body_20_39
410          eval(shift(@insns));
411          eval(shift(@insns))            if (@insns[1] =~ /_ror/);
412          eval(shift(@insns))            if (@insns[0] =~ /_ror/);
413         &punpcklqdq(@Tx[0],@X[-1&7]);   # compose "X[-6]", was &palignr(@Tx[0],@X[-2&7],8);
414          eval(shift(@insns));
415          eval(shift(@insns));           # rol
416
417         &pxor   (@X[0],@X[-7&7]);       # "X[0]"^="X[-28]"
418          eval(shift(@insns));
419          eval(shift(@insns));
420         if ($Xi%5) {
421           &movdqa       (@Tx[2],@Tx[1]);# "perpetuate" K_XX_XX...
422         } else {                        # ... or load next one
423           &movdqa       (@Tx[2],eval(16*($Xi/5))."($K_XX_XX)");
424         }
425          eval(shift(@insns));           # ror
426           &paddd        (@Tx[1],@X[-1&7]);
427          eval(shift(@insns));
428
429         &pxor   (@X[0],@Tx[0]);         # "X[0]"^="X[-6]"
430          eval(shift(@insns));           # body_20_39
431          eval(shift(@insns));
432          eval(shift(@insns));
433          eval(shift(@insns));           # rol
434          eval(shift(@insns))            if (@insns[0] =~ /_ror/);
435
436         &movdqa (@Tx[0],@X[0]);
437          eval(shift(@insns));
438          eval(shift(@insns));
439           &movdqa       (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
440          eval(shift(@insns));           # ror
441          eval(shift(@insns));
442          eval(shift(@insns));           # body_20_39
443
444         &pslld  (@X[0],2);
445          eval(shift(@insns));
446          eval(shift(@insns));
447         &psrld  (@Tx[0],30);
448          eval(shift(@insns))            if (@insns[0] =~ /_rol/);# rol
449          eval(shift(@insns));
450          eval(shift(@insns));
451          eval(shift(@insns));           # ror
452
453         &por    (@X[0],@Tx[0]);         # "X[0]"<<<=2
454          eval(shift(@insns));
455          eval(shift(@insns));           # body_20_39
456          eval(shift(@insns))            if (@insns[1] =~ /_rol/);
457          eval(shift(@insns))            if (@insns[0] =~ /_rol/);
458           &pshufd(@Tx[1],@X[-1&7],0xee) if ($Xi<19);    # was &movdqa   (@Tx[1],@X[0])
459          eval(shift(@insns));
460          eval(shift(@insns));           # rol
461          eval(shift(@insns));
462          eval(shift(@insns));
463          eval(shift(@insns));           # rol
464          eval(shift(@insns));
465
466          foreach (@insns) { eval; }     # remaining instructions
467
468   $Xi++;        push(@X,shift(@X));     # "rotate" X[]
469                 push(@Tx,shift(@Tx));
470 }
471
472 sub Xuplast_ssse3_80()
473 { use integer;
474   my $body = shift;
475   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
476   my ($a,$b,$c,$d,$e);
477
478          eval(shift(@insns));
479          eval(shift(@insns));
480          eval(shift(@insns));
481          eval(shift(@insns));
482           &paddd        (@Tx[1],@X[-1&7]);
483          eval(shift(@insns));
484          eval(shift(@insns));
485
486           &movdqa       (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU
487
488          foreach (@insns) { eval; }             # remaining instructions
489
490         &cmp    ($inp,$len);
491         &je     (shift);
492
493         unshift(@Tx,pop(@Tx));
494
495         &movdqa (@Tx[2],"64($K_XX_XX)");        # pbswap mask
496         &movdqa (@Tx[1],"0($K_XX_XX)");         # K_00_19
497         &movdqu (@X[-4&7],"0($inp)");           # load input
498         &movdqu (@X[-3&7],"16($inp)");
499         &movdqu (@X[-2&7],"32($inp)");
500         &movdqu (@X[-1&7],"48($inp)");
501         &pshufb (@X[-4&7],@Tx[2]);              # byte swap
502         &add    ($inp,64);
503
504   $Xi=0;
505 }
506
507 sub Xloop_ssse3()
508 { use integer;
509   my $body = shift;
510   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
511   my ($a,$b,$c,$d,$e);
512
513          eval(shift(@insns));
514          eval(shift(@insns));
515          eval(shift(@insns));
516         &pshufb (@X[($Xi-3)&7],@Tx[2]);
517          eval(shift(@insns));
518          eval(shift(@insns));
519          eval(shift(@insns));
520          eval(shift(@insns));
521         &paddd  (@X[($Xi-4)&7],@Tx[1]);
522          eval(shift(@insns));
523          eval(shift(@insns));
524          eval(shift(@insns));
525          eval(shift(@insns));
526         &movdqa (eval(16*$Xi)."(%rsp)",@X[($Xi-4)&7]);  # X[]+K xfer to IALU
527          eval(shift(@insns));
528          eval(shift(@insns));
529          eval(shift(@insns));
530          eval(shift(@insns));
531         &psubd  (@X[($Xi-4)&7],@Tx[1]);
532
533         foreach (@insns) { eval; }
534   $Xi++;
535 }
536
537 sub Xtail_ssse3()
538 { use integer;
539   my $body = shift;
540   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
541   my ($a,$b,$c,$d,$e);
542
543         foreach (@insns) { eval; }
544 }
545
546 my @body_00_19 = (
547         '($a,$b,$c,$d,$e)=@V;'.
548         '&$_ror ($b,$j?7:2);',  # $b>>>2
549         '&xor   (@T[0],$d);',
550         '&mov   (@T[1],$a);',   # $b for next round
551
552         '&add   ($e,eval(4*($j&15))."(%rsp)");',# X[]+K xfer
553         '&xor   ($b,$c);',      # $c^$d for next round
554
555         '&$_rol ($a,5);',
556         '&add   ($e,@T[0]);',
557         '&and   (@T[1],$b);',   # ($b&($c^$d)) for next round
558
559         '&xor   ($b,$c);',      # restore $b
560         '&add   ($e,$a);'       .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
561         );
562
563 sub body_00_19 () {     # ((c^d)&b)^d
564     # on start @T[0]=(c^d)&b
565     return &body_20_39() if ($rx==19); $rx++;
566
567     use integer;
568     my ($k,$n);
569     my @r=@body_00_19;
570
571         $n = scalar(@r);
572         $k = (($jj+1)*12/20)*20*$n/12;  # 12 aesencs per these 20 rounds
573         @r[$k%$n].='&$aesenc();'        if ($jj==$k/$n);
574         $jj++;
575
576     return @r;
577 }
578
579 my @body_20_39 = (
580         '($a,$b,$c,$d,$e)=@V;'.
581         '&add   ($e,eval(4*($j&15))."(%rsp)");',# X[]+K xfer
582         '&xor   (@T[0],$d)      if($j==19);'.
583         '&xor   (@T[0],$c)      if($j> 19);',   # ($b^$d^$c)
584         '&mov   (@T[1],$a);',   # $b for next round
585
586         '&$_rol ($a,5);',
587         '&add   ($e,@T[0]);',
588         '&xor   (@T[1],$c)      if ($j< 79);',  # $b^$d for next round
589
590         '&$_ror ($b,7);',       # $b>>>2
591         '&add   ($e,$a);'       .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
592         );
593
594 sub body_20_39 () {     # b^d^c
595     # on entry @T[0]=b^d
596     return &body_40_59() if ($rx==39); $rx++;
597
598     use integer;
599     my ($k,$n);
600     my @r=@body_20_39;
601
602         $n = scalar(@r);
603         $k = (($jj+1)*8/20)*20*$n/8;    # 8 aesencs per these 20 rounds
604         @r[$k%$n].='&$aesenc();'        if ($jj==$k/$n && $rx!=20);
605         $jj++;
606
607     return @r;
608 }
609
610 my @body_40_59 = (
611         '($a,$b,$c,$d,$e)=@V;'.
612         '&add   ($e,eval(4*($j&15))."(%rsp)");',# X[]+K xfer
613         '&and   (@T[0],$c)      if ($j>=40);',  # (b^c)&(c^d)
614         '&xor   ($c,$d)         if ($j>=40);',  # restore $c
615
616         '&$_ror ($b,7);',       # $b>>>2
617         '&mov   (@T[1],$a);',   # $b for next round
618         '&xor   (@T[0],$c);',
619
620         '&$_rol ($a,5);',
621         '&add   ($e,@T[0]);',
622         '&xor   (@T[1],$c)      if ($j==59);'.
623         '&xor   (@T[1],$b)      if ($j< 59);',  # b^c for next round
624
625         '&xor   ($b,$c)         if ($j< 59);',  # c^d for next round
626         '&add   ($e,$a);'       .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
627         );
628
629 sub body_40_59 () {     # ((b^c)&(c^d))^c
630     # on entry @T[0]=(b^c), (c^=d)
631     $rx++;
632
633     use integer;
634     my ($k,$n);
635     my @r=@body_40_59;
636
637         $n = scalar(@r);
638         $k=(($jj+1)*12/20)*20*$n/12;    # 12 aesencs per these 20 rounds
639         @r[$k%$n].='&$aesenc();'        if ($jj==$k/$n && $rx!=40);
640         $jj++;
641
642     return @r;
643 }
644 $code.=<<___;
645 .align  32
646 .Loop_ssse3:
647 ___
648         &Xupdate_ssse3_16_31(\&body_00_19);
649         &Xupdate_ssse3_16_31(\&body_00_19);
650         &Xupdate_ssse3_16_31(\&body_00_19);
651         &Xupdate_ssse3_16_31(\&body_00_19);
652         &Xupdate_ssse3_32_79(\&body_00_19);
653         &Xupdate_ssse3_32_79(\&body_20_39);
654         &Xupdate_ssse3_32_79(\&body_20_39);
655         &Xupdate_ssse3_32_79(\&body_20_39);
656         &Xupdate_ssse3_32_79(\&body_20_39);
657         &Xupdate_ssse3_32_79(\&body_20_39);
658         &Xupdate_ssse3_32_79(\&body_40_59);
659         &Xupdate_ssse3_32_79(\&body_40_59);
660         &Xupdate_ssse3_32_79(\&body_40_59);
661         &Xupdate_ssse3_32_79(\&body_40_59);
662         &Xupdate_ssse3_32_79(\&body_40_59);
663         &Xupdate_ssse3_32_79(\&body_20_39);
664         &Xuplast_ssse3_80(\&body_20_39,".Ldone_ssse3"); # can jump to "done"
665
666                                 $saved_j=$j; @saved_V=@V;
667                                 $saved_r=$r; @saved_rndkey=@rndkey;
668
669         &Xloop_ssse3(\&body_20_39);
670         &Xloop_ssse3(\&body_20_39);
671         &Xloop_ssse3(\&body_20_39);
672
673 $code.=<<___;
674         movups  $iv,48($out,$in0)               # write output
675         lea     64($in0),$in0
676
677         add     0($ctx),$A                      # update context
678         add     4($ctx),@T[0]
679         add     8($ctx),$C
680         add     12($ctx),$D
681         mov     $A,0($ctx)
682         add     16($ctx),$E
683         mov     @T[0],4($ctx)
684         mov     @T[0],$B                        # magic seed
685         mov     $C,8($ctx)
686         mov     $C,@T[1]
687         mov     $D,12($ctx)
688         xor     $D,@T[1]
689         mov     $E,16($ctx)
690         and     @T[1],@T[0]
691         jmp     .Loop_ssse3
692
693 .Ldone_ssse3:
694 ___
695                                 $jj=$j=$saved_j; @V=@saved_V;
696                                 $r=$saved_r;     @rndkey=@saved_rndkey;
697
698         &Xtail_ssse3(\&body_20_39);
699         &Xtail_ssse3(\&body_20_39);
700         &Xtail_ssse3(\&body_20_39);
701
702 $code.=<<___;
703         movups  $iv,48($out,$in0)               # write output
704         mov     88(%rsp),$ivp                   # restore $ivp
705
706         add     0($ctx),$A                      # update context
707         add     4($ctx),@T[0]
708         add     8($ctx),$C
709         mov     $A,0($ctx)
710         add     12($ctx),$D
711         mov     @T[0],4($ctx)
712         add     16($ctx),$E
713         mov     $C,8($ctx)
714         mov     $D,12($ctx)
715         mov     $E,16($ctx)
716         movups  $iv,($ivp)                      # write IV
717 ___
718 $code.=<<___ if ($win64);
719         movaps  96+0(%rsp),%xmm6
720         movaps  96+16(%rsp),%xmm7
721         movaps  96+32(%rsp),%xmm8
722         movaps  96+48(%rsp),%xmm9
723         movaps  96+64(%rsp),%xmm10
724         movaps  96+80(%rsp),%xmm11
725         movaps  96+96(%rsp),%xmm12
726         movaps  96+112(%rsp),%xmm13
727         movaps  96+128(%rsp),%xmm14
728         movaps  96+144(%rsp),%xmm15
729 ___
730 $code.=<<___;
731         lea     `104+($win64?10*16:0)`(%rsp),%rsi
732 .cfi_def_cfa    %rsi,56
733         mov     0(%rsi),%r15
734 .cfi_restore    %r15
735         mov     8(%rsi),%r14
736 .cfi_restore    %r14
737         mov     16(%rsi),%r13
738 .cfi_restore    %r13
739         mov     24(%rsi),%r12
740 .cfi_restore    %r12
741         mov     32(%rsi),%rbp
742 .cfi_restore    %rbp
743         mov     40(%rsi),%rbx
744 .cfi_restore    %rbx
745         lea     48(%rsi),%rsp
746 .cfi_def_cfa    %rsp,8
747 .Lepilogue_ssse3:
748         ret
749 .cfi_endproc
750 .size   aesni_cbc_sha1_enc_ssse3,.-aesni_cbc_sha1_enc_ssse3
751 ___
752
753                                                 if ($stitched_decrypt) {{{
754 # reset
755 ($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10");
756 $j=$jj=$r=$rx=0;
757 $Xi=4;
758
759 # reassign for Atom Silvermont (see above)
760 ($inout0,$inout1,$inout2,$inout3,$rndkey0)=map("%xmm$_",(0..4));
761 @X=map("%xmm$_",(8..13,6,7));
762 @Tx=map("%xmm$_",(14,15,5));
763
764 my @aes256_dec = (
765         '&movdqu($inout0,"0x00($in0)");',
766         '&movdqu($inout1,"0x10($in0)"); &pxor   ($inout0,$rndkey0);',
767         '&movdqu($inout2,"0x20($in0)"); &pxor   ($inout1,$rndkey0);',
768         '&movdqu($inout3,"0x30($in0)"); &pxor   ($inout2,$rndkey0);',
769
770         '&pxor  ($inout3,$rndkey0);     &movups ($rndkey0,"16-112($key)");',
771         '&movaps("64(%rsp)",@X[2]);',   # save IV, originally @X[3]
772         undef,undef
773         );
774 for ($i=0;$i<13;$i++) {
775     push (@aes256_dec,(
776         '&aesdec        ($inout0,$rndkey0);',
777         '&aesdec        ($inout1,$rndkey0);',
778         '&aesdec        ($inout2,$rndkey0);',
779         '&aesdec        ($inout3,$rndkey0);     &movups($rndkey0,"'.(16*($i+2)-112).'($key)");'
780         ));
781     push (@aes256_dec,(undef,undef))    if (($i>=3 && $i<=5) || $i>=11);
782     push (@aes256_dec,(undef,undef))    if ($i==5);
783 }
784 push(@aes256_dec,(
785         '&aesdeclast    ($inout0,$rndkey0);     &movups (@X[0],"0x00($in0)");',
786         '&aesdeclast    ($inout1,$rndkey0);     &movups (@X[1],"0x10($in0)");',
787         '&aesdeclast    ($inout2,$rndkey0);     &movups (@X[2],"0x20($in0)");',
788         '&aesdeclast    ($inout3,$rndkey0);     &movups (@X[3],"0x30($in0)");',
789
790         '&xorps         ($inout0,"64(%rsp)");   &movdqu ($rndkey0,"-112($key)");',
791         '&xorps         ($inout1,@X[0]);        &movups ("0x00($out,$in0)",$inout0);',
792         '&xorps         ($inout2,@X[1]);        &movups ("0x10($out,$in0)",$inout1);',
793         '&xorps         ($inout3,@X[2]);        &movups ("0x20($out,$in0)",$inout2);',
794
795         '&movups        ("0x30($out,$in0)",$inout3);'
796         ));
797
798 sub body_00_19_dec () { # ((c^d)&b)^d
799     # on start @T[0]=(c^d)&b
800     return &body_20_39_dec() if ($rx==19);
801
802     my @r=@body_00_19;
803
804         unshift (@r,@aes256_dec[$rx])   if (@aes256_dec[$rx]);
805         $rx++;
806
807     return @r;
808 }
809
810 sub body_20_39_dec () { # b^d^c
811     # on entry @T[0]=b^d
812     return &body_40_59_dec() if ($rx==39);
813
814     my @r=@body_20_39;
815
816         unshift (@r,@aes256_dec[$rx])   if (@aes256_dec[$rx]);
817         $rx++;
818
819     return @r;
820 }
821
822 sub body_40_59_dec () { # ((b^c)&(c^d))^c
823     # on entry @T[0]=(b^c), (c^=d)
824
825     my @r=@body_40_59;
826
827         unshift (@r,@aes256_dec[$rx])   if (@aes256_dec[$rx]);
828         $rx++;
829
830     return @r;
831 }
832
833 $code.=<<___;
834 .globl  aesni256_cbc_sha1_dec
835 .type   aesni256_cbc_sha1_dec,\@abi-omnipotent
836 .align  32
837 aesni256_cbc_sha1_dec:
838         # caller should check for SSSE3 and AES-NI bits
839         mov     OPENSSL_ia32cap_P+0(%rip),%r10d
840         mov     OPENSSL_ia32cap_P+4(%rip),%r11d
841 ___
842 $code.=<<___ if ($avx);
843         and     \$`1<<28`,%r11d         # mask AVX bit
844         and     \$`1<<30`,%r10d         # mask "Intel CPU" bit
845         or      %r11d,%r10d
846         cmp     \$`1<<28|1<<30`,%r10d
847         je      aesni256_cbc_sha1_dec_avx
848 ___
849 $code.=<<___;
850         jmp     aesni256_cbc_sha1_dec_ssse3
851         ret
852 .size   aesni256_cbc_sha1_dec,.-aesni256_cbc_sha1_dec
853
854 .type   aesni256_cbc_sha1_dec_ssse3,\@function,6
855 .align  32
856 aesni256_cbc_sha1_dec_ssse3:
857 .cfi_startproc
858         mov     `($win64?56:8)`(%rsp),$inp      # load 7th argument
859         push    %rbx
860 .cfi_push       %rbx
861         push    %rbp
862 .cfi_push       %rbp
863         push    %r12
864 .cfi_push       %r12
865         push    %r13
866 .cfi_push       %r13
867         push    %r14
868 .cfi_push       %r14
869         push    %r15
870 .cfi_push       %r15
871         lea     `-104-($win64?10*16:0)`(%rsp),%rsp
872 .cfi_adjust_cfa_offset  `104+($win64?10*16:0)`
873 ___
874 $code.=<<___ if ($win64);
875         movaps  %xmm6,96+0(%rsp)
876         movaps  %xmm7,96+16(%rsp)
877         movaps  %xmm8,96+32(%rsp)
878         movaps  %xmm9,96+48(%rsp)
879         movaps  %xmm10,96+64(%rsp)
880         movaps  %xmm11,96+80(%rsp)
881         movaps  %xmm12,96+96(%rsp)
882         movaps  %xmm13,96+112(%rsp)
883         movaps  %xmm14,96+128(%rsp)
884         movaps  %xmm15,96+144(%rsp)
885 .Lprologue_dec_ssse3:
886 ___
887 $code.=<<___;
888         mov     $in0,%r12                       # reassign arguments
889         mov     $out,%r13
890         mov     $len,%r14
891         lea     112($key),%r15                  # size optimization
892         movdqu  ($ivp),@X[3]                    # load IV
893         #mov    $ivp,88(%rsp)                   # save $ivp
894 ___
895 ($in0,$out,$len,$key)=map("%r$_",(12..15));     # reassign arguments
896 $code.=<<___;
897         shl     \$6,$len
898         sub     $in0,$out
899         add     $inp,$len               # end of input
900
901         lea     K_XX_XX(%rip),$K_XX_XX
902         mov     0($ctx),$A              # load context
903         mov     4($ctx),$B
904         mov     8($ctx),$C
905         mov     12($ctx),$D
906         mov     $B,@T[0]                # magic seed
907         mov     16($ctx),$E
908         mov     $C,@T[1]
909         xor     $D,@T[1]
910         and     @T[1],@T[0]
911
912         movdqa  64($K_XX_XX),@Tx[2]     # pbswap mask
913         movdqa  0($K_XX_XX),@Tx[1]      # K_00_19
914         movdqu  0($inp),@X[-4&7]        # load input to %xmm[0-3]
915         movdqu  16($inp),@X[-3&7]
916         movdqu  32($inp),@X[-2&7]
917         movdqu  48($inp),@X[-1&7]
918         pshufb  @Tx[2],@X[-4&7]         # byte swap
919         add     \$64,$inp
920         pshufb  @Tx[2],@X[-3&7]
921         pshufb  @Tx[2],@X[-2&7]
922         pshufb  @Tx[2],@X[-1&7]
923         paddd   @Tx[1],@X[-4&7]         # add K_00_19
924         paddd   @Tx[1],@X[-3&7]
925         paddd   @Tx[1],@X[-2&7]
926         movdqa  @X[-4&7],0(%rsp)        # X[]+K xfer to IALU
927         psubd   @Tx[1],@X[-4&7]         # restore X[]
928         movdqa  @X[-3&7],16(%rsp)
929         psubd   @Tx[1],@X[-3&7]
930         movdqa  @X[-2&7],32(%rsp)
931         psubd   @Tx[1],@X[-2&7]
932         movdqu  -112($key),$rndkey0     # $key[0]
933         jmp     .Loop_dec_ssse3
934
935 .align  32
936 .Loop_dec_ssse3:
937 ___
938         &Xupdate_ssse3_16_31(\&body_00_19_dec);
939         &Xupdate_ssse3_16_31(\&body_00_19_dec);
940         &Xupdate_ssse3_16_31(\&body_00_19_dec);
941         &Xupdate_ssse3_16_31(\&body_00_19_dec);
942         &Xupdate_ssse3_32_79(\&body_00_19_dec);
943         &Xupdate_ssse3_32_79(\&body_20_39_dec);
944         &Xupdate_ssse3_32_79(\&body_20_39_dec);
945         &Xupdate_ssse3_32_79(\&body_20_39_dec);
946         &Xupdate_ssse3_32_79(\&body_20_39_dec);
947         &Xupdate_ssse3_32_79(\&body_20_39_dec);
948         &Xupdate_ssse3_32_79(\&body_40_59_dec);
949         &Xupdate_ssse3_32_79(\&body_40_59_dec);
950         &Xupdate_ssse3_32_79(\&body_40_59_dec);
951         &Xupdate_ssse3_32_79(\&body_40_59_dec);
952         &Xupdate_ssse3_32_79(\&body_40_59_dec);
953         &Xupdate_ssse3_32_79(\&body_20_39_dec);
954         &Xuplast_ssse3_80(\&body_20_39_dec,".Ldone_dec_ssse3"); # can jump to "done"
955
956                                 $saved_j=$j;   @saved_V=@V;
957                                 $saved_rx=$rx;
958
959         &Xloop_ssse3(\&body_20_39_dec);
960         &Xloop_ssse3(\&body_20_39_dec);
961         &Xloop_ssse3(\&body_20_39_dec);
962
963         eval(@aes256_dec[-1]);                  # last store
964 $code.=<<___;
965         lea     64($in0),$in0
966
967         add     0($ctx),$A                      # update context
968         add     4($ctx),@T[0]
969         add     8($ctx),$C
970         add     12($ctx),$D
971         mov     $A,0($ctx)
972         add     16($ctx),$E
973         mov     @T[0],4($ctx)
974         mov     @T[0],$B                        # magic seed
975         mov     $C,8($ctx)
976         mov     $C,@T[1]
977         mov     $D,12($ctx)
978         xor     $D,@T[1]
979         mov     $E,16($ctx)
980         and     @T[1],@T[0]
981         jmp     .Loop_dec_ssse3
982
983 .Ldone_dec_ssse3:
984 ___
985                                 $jj=$j=$saved_j; @V=@saved_V;
986                                 $rx=$saved_rx;
987
988         &Xtail_ssse3(\&body_20_39_dec);
989         &Xtail_ssse3(\&body_20_39_dec);
990         &Xtail_ssse3(\&body_20_39_dec);
991
992         eval(@aes256_dec[-1]);                  # last store
993 $code.=<<___;
994         add     0($ctx),$A                      # update context
995         add     4($ctx),@T[0]
996         add     8($ctx),$C
997         mov     $A,0($ctx)
998         add     12($ctx),$D
999         mov     @T[0],4($ctx)
1000         add     16($ctx),$E
1001         mov     $C,8($ctx)
1002         mov     $D,12($ctx)
1003         mov     $E,16($ctx)
1004         movups  @X[3],($ivp)                    # write IV
1005 ___
1006 $code.=<<___ if ($win64);
1007         movaps  96+0(%rsp),%xmm6
1008         movaps  96+16(%rsp),%xmm7
1009         movaps  96+32(%rsp),%xmm8
1010         movaps  96+48(%rsp),%xmm9
1011         movaps  96+64(%rsp),%xmm10
1012         movaps  96+80(%rsp),%xmm11
1013         movaps  96+96(%rsp),%xmm12
1014         movaps  96+112(%rsp),%xmm13
1015         movaps  96+128(%rsp),%xmm14
1016         movaps  96+144(%rsp),%xmm15
1017 ___
1018 $code.=<<___;
1019         lea     `104+($win64?10*16:0)`(%rsp),%rsi
1020 .cfi_cfa_def    %rsi,56
1021         mov     0(%rsi),%r15
1022 .cfi_restore    %r15
1023         mov     8(%rsi),%r14
1024 .cfi_restore    %r14
1025         mov     16(%rsi),%r13
1026 .cfi_restore    %r13
1027         mov     24(%rsi),%r12
1028 .cfi_restore    %r12
1029         mov     32(%rsi),%rbp
1030 .cfi_restore    %rbp
1031         mov     40(%rsi),%rbx
1032 .cfi_restore    %rbx
1033         lea     48(%rsi),%rsp
1034 .cfi_cfa_def    %rsp,8
1035 .Lepilogue_dec_ssse3:
1036         ret
1037 .cfi_endproc
1038 .size   aesni256_cbc_sha1_dec_ssse3,.-aesni256_cbc_sha1_dec_ssse3
1039 ___
1040                                                 }}}
1041 $j=$jj=$r=$rx=0;
1042
1043 if ($avx) {
1044 my ($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10");
1045
1046 my $Xi=4;
1047 my @X=map("%xmm$_",(4..7,0..3));
1048 my @Tx=map("%xmm$_",(8..10));
1049 my @V=($A,$B,$C,$D,$E)=("%eax","%ebx","%ecx","%edx","%ebp");    # size optimization
1050 my @T=("%esi","%edi");
1051 my ($rndkey0,$iv,$in)=map("%xmm$_",(11..13));
1052 my @rndkey=("%xmm14","%xmm15");
1053 my ($inout0,$inout1,$inout2,$inout3)=map("%xmm$_",(12..15));    # for dec
1054 my $Kx=@Tx[2];
1055
1056 my $_rol=sub { &shld(@_[0],@_) };
1057 my $_ror=sub { &shrd(@_[0],@_) };
1058
1059 $code.=<<___;
1060 .type   aesni_cbc_sha1_enc_avx,\@function,6
1061 .align  32
1062 aesni_cbc_sha1_enc_avx:
1063 .cfi_startproc
1064         mov     `($win64?56:8)`(%rsp),$inp      # load 7th argument
1065         #shr    \$6,$len                        # debugging artefact
1066         #jz     .Lepilogue_avx                  # debugging artefact
1067         push    %rbx
1068 .cfi_push       %rbx
1069         push    %rbp
1070 .cfi_push       %rbp
1071         push    %r12
1072 .cfi_push       %r12
1073         push    %r13
1074 .cfi_push       %r13
1075         push    %r14
1076 .cfi_push       %r14
1077         push    %r15
1078 .cfi_push       %r15
1079         lea     `-104-($win64?10*16:0)`(%rsp),%rsp
1080 .cfi_adjust_cfa_offset  `104+($win64?10*16:0)`
1081         #mov    $in0,$inp                       # debugging artefact
1082         #lea    64(%rsp),$ctx                   # debugging artefact
1083 ___
1084 $code.=<<___ if ($win64);
1085         movaps  %xmm6,96+0(%rsp)
1086         movaps  %xmm7,96+16(%rsp)
1087         movaps  %xmm8,96+32(%rsp)
1088         movaps  %xmm9,96+48(%rsp)
1089         movaps  %xmm10,96+64(%rsp)
1090         movaps  %xmm11,96+80(%rsp)
1091         movaps  %xmm12,96+96(%rsp)
1092         movaps  %xmm13,96+112(%rsp)
1093         movaps  %xmm14,96+128(%rsp)
1094         movaps  %xmm15,96+144(%rsp)
1095 .Lprologue_avx:
1096 ___
1097 $code.=<<___;
1098         vzeroall
1099         mov     $in0,%r12                       # reassign arguments
1100         mov     $out,%r13
1101         mov     $len,%r14
1102         lea     112($key),%r15                  # size optimization
1103         vmovdqu ($ivp),$iv                      # load IV
1104         mov     $ivp,88(%rsp)                   # save $ivp
1105 ___
1106 ($in0,$out,$len,$key)=map("%r$_",(12..15));     # reassign arguments
1107 my $rounds="${ivp}d";
1108 $code.=<<___;
1109         shl     \$6,$len
1110         sub     $in0,$out
1111         mov     240-112($key),$rounds
1112         add     $inp,$len               # end of input
1113
1114         lea     K_XX_XX(%rip),$K_XX_XX
1115         mov     0($ctx),$A              # load context
1116         mov     4($ctx),$B
1117         mov     8($ctx),$C
1118         mov     12($ctx),$D
1119         mov     $B,@T[0]                # magic seed
1120         mov     16($ctx),$E
1121         mov     $C,@T[1]
1122         xor     $D,@T[1]
1123         and     @T[1],@T[0]
1124
1125         vmovdqa 64($K_XX_XX),@X[2]      # pbswap mask
1126         vmovdqa 0($K_XX_XX),$Kx         # K_00_19
1127         vmovdqu 0($inp),@X[-4&7]        # load input to %xmm[0-3]
1128         vmovdqu 16($inp),@X[-3&7]
1129         vmovdqu 32($inp),@X[-2&7]
1130         vmovdqu 48($inp),@X[-1&7]
1131         vpshufb @X[2],@X[-4&7],@X[-4&7] # byte swap
1132         add     \$64,$inp
1133         vpshufb @X[2],@X[-3&7],@X[-3&7]
1134         vpshufb @X[2],@X[-2&7],@X[-2&7]
1135         vpshufb @X[2],@X[-1&7],@X[-1&7]
1136         vpaddd  $Kx,@X[-4&7],@X[0]      # add K_00_19
1137         vpaddd  $Kx,@X[-3&7],@X[1]
1138         vpaddd  $Kx,@X[-2&7],@X[2]
1139         vmovdqa @X[0],0(%rsp)           # X[]+K xfer to IALU
1140         vmovdqa @X[1],16(%rsp)
1141         vmovdqa @X[2],32(%rsp)
1142         vmovups -112($key),$rndkey[1]   # $key[0]
1143         vmovups 16-112($key),$rndkey[0] # forward reference
1144         jmp     .Loop_avx
1145 ___
1146
1147 my $aesenc=sub {
1148   use integer;
1149   my ($n,$k)=($r/10,$r%10);
1150     if ($k==0) {
1151       $code.=<<___;
1152         vmovdqu         `16*$n`($in0),$in               # load input
1153         vpxor           $rndkey[1],$in,$in
1154 ___
1155       $code.=<<___ if ($n);
1156         vmovups         $iv,`16*($n-1)`($out,$in0)      # write output
1157 ___
1158       $code.=<<___;
1159         vpxor           $in,$iv,$iv
1160         vaesenc         $rndkey[0],$iv,$iv
1161         vmovups         `32+16*$k-112`($key),$rndkey[1]
1162 ___
1163     } elsif ($k==9) {
1164       $sn++;
1165       $code.=<<___;
1166         cmp             \$11,$rounds
1167         jb              .Lvaesenclast$sn
1168         vaesenc         $rndkey[0],$iv,$iv
1169         vmovups         `32+16*($k+0)-112`($key),$rndkey[1]
1170         vaesenc         $rndkey[1],$iv,$iv
1171         vmovups         `32+16*($k+1)-112`($key),$rndkey[0]
1172         je              .Lvaesenclast$sn
1173         vaesenc         $rndkey[0],$iv,$iv
1174         vmovups         `32+16*($k+2)-112`($key),$rndkey[1]
1175         vaesenc         $rndkey[1],$iv,$iv
1176         vmovups         `32+16*($k+3)-112`($key),$rndkey[0]
1177 .Lvaesenclast$sn:
1178         vaesenclast     $rndkey[0],$iv,$iv
1179         vmovups         -112($key),$rndkey[0]
1180         vmovups         16-112($key),$rndkey[1]         # forward reference
1181 ___
1182     } else {
1183       $code.=<<___;
1184         vaesenc         $rndkey[0],$iv,$iv
1185         vmovups         `32+16*$k-112`($key),$rndkey[1]
1186 ___
1187     }
1188     $r++;       unshift(@rndkey,pop(@rndkey));
1189 };
1190
1191 sub Xupdate_avx_16_31()         # recall that $Xi starts wtih 4
1192 { use integer;
1193   my $body = shift;
1194   my @insns = (&$body,&$body,&$body,&$body);    # 40 instructions
1195   my ($a,$b,$c,$d,$e);
1196
1197          eval(shift(@insns));
1198          eval(shift(@insns));
1199         &vpalignr(@X[0],@X[-3&7],@X[-4&7],8);   # compose "X[-14]" in "X[0]"
1200          eval(shift(@insns));
1201          eval(shift(@insns));
1202
1203           &vpaddd       (@Tx[1],$Kx,@X[-1&7]);
1204          eval(shift(@insns));
1205          eval(shift(@insns));
1206         &vpsrldq(@Tx[0],@X[-1&7],4);            # "X[-3]", 3 dwords
1207          eval(shift(@insns));
1208          eval(shift(@insns));
1209         &vpxor  (@X[0],@X[0],@X[-4&7]);         # "X[0]"^="X[-16]"
1210          eval(shift(@insns));
1211          eval(shift(@insns));
1212
1213         &vpxor  (@Tx[0],@Tx[0],@X[-2&7]);       # "X[-3]"^"X[-8]"
1214          eval(shift(@insns));
1215          eval(shift(@insns));
1216          eval(shift(@insns));
1217          eval(shift(@insns));
1218
1219         &vpxor  (@X[0],@X[0],@Tx[0]);           # "X[0]"^="X[-3]"^"X[-8]"
1220          eval(shift(@insns));
1221          eval(shift(@insns));
1222           &vmovdqa      (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
1223          eval(shift(@insns));
1224          eval(shift(@insns));
1225
1226         &vpsrld (@Tx[0],@X[0],31);
1227          eval(shift(@insns));
1228          eval(shift(@insns));
1229          eval(shift(@insns));
1230          eval(shift(@insns));
1231
1232         &vpslldq(@Tx[1],@X[0],12);              # "X[0]"<<96, extract one dword
1233         &vpaddd (@X[0],@X[0],@X[0]);
1234          eval(shift(@insns));
1235          eval(shift(@insns));
1236          eval(shift(@insns));
1237          eval(shift(@insns));
1238
1239         &vpor   (@X[0],@X[0],@Tx[0]);           # "X[0]"<<<=1
1240         &vpsrld (@Tx[0],@Tx[1],30);
1241          eval(shift(@insns));
1242          eval(shift(@insns));
1243          eval(shift(@insns));
1244          eval(shift(@insns));
1245
1246         &vpslld (@Tx[1],@Tx[1],2);
1247         &vpxor  (@X[0],@X[0],@Tx[0]);
1248          eval(shift(@insns));
1249          eval(shift(@insns));
1250          eval(shift(@insns));
1251          eval(shift(@insns));
1252
1253         &vpxor  (@X[0],@X[0],@Tx[1]);           # "X[0]"^=("X[0]">>96)<<<2
1254          eval(shift(@insns));
1255          eval(shift(@insns));
1256           &vmovdqa      ($Kx,eval(16*(($Xi)/5))."($K_XX_XX)")   if ($Xi%5==0);  # K_XX_XX
1257          eval(shift(@insns));
1258          eval(shift(@insns));
1259
1260
1261          foreach (@insns) { eval; }     # remaining instructions [if any]
1262
1263   $Xi++;        push(@X,shift(@X));     # "rotate" X[]
1264 }
1265
1266 sub Xupdate_avx_32_79()
1267 { use integer;
1268   my $body = shift;
1269   my @insns = (&$body,&$body,&$body,&$body);    # 32 to 48 instructions
1270   my ($a,$b,$c,$d,$e);
1271
1272         &vpalignr(@Tx[0],@X[-1&7],@X[-2&7],8);  # compose "X[-6]"
1273         &vpxor  (@X[0],@X[0],@X[-4&7]);         # "X[0]"="X[-32]"^"X[-16]"
1274          eval(shift(@insns));           # body_20_39
1275          eval(shift(@insns));
1276          eval(shift(@insns));
1277          eval(shift(@insns));           # rol
1278
1279         &vpxor  (@X[0],@X[0],@X[-7&7]);         # "X[0]"^="X[-28]"
1280          eval(shift(@insns));
1281          eval(shift(@insns))    if (@insns[0] !~ /&ro[rl]/);
1282           &vpaddd       (@Tx[1],$Kx,@X[-1&7]);
1283           &vmovdqa      ($Kx,eval(16*($Xi/5))."($K_XX_XX)")     if ($Xi%5==0);
1284          eval(shift(@insns));           # ror
1285          eval(shift(@insns));
1286
1287         &vpxor  (@X[0],@X[0],@Tx[0]);           # "X[0]"^="X[-6]"
1288          eval(shift(@insns));           # body_20_39
1289          eval(shift(@insns));
1290          eval(shift(@insns));
1291          eval(shift(@insns));           # rol
1292
1293         &vpsrld (@Tx[0],@X[0],30);
1294           &vmovdqa      (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
1295          eval(shift(@insns));
1296          eval(shift(@insns));
1297          eval(shift(@insns));           # ror
1298          eval(shift(@insns));
1299
1300         &vpslld (@X[0],@X[0],2);
1301          eval(shift(@insns));           # body_20_39
1302          eval(shift(@insns));
1303          eval(shift(@insns));
1304          eval(shift(@insns));           # rol
1305          eval(shift(@insns));
1306          eval(shift(@insns));
1307          eval(shift(@insns));           # ror
1308          eval(shift(@insns));
1309
1310         &vpor   (@X[0],@X[0],@Tx[0]);           # "X[0]"<<<=2
1311          eval(shift(@insns));           # body_20_39
1312          eval(shift(@insns));
1313          eval(shift(@insns));
1314          eval(shift(@insns));           # rol
1315          eval(shift(@insns));
1316          eval(shift(@insns));
1317          eval(shift(@insns));           # rol
1318          eval(shift(@insns));
1319
1320          foreach (@insns) { eval; }     # remaining instructions
1321
1322   $Xi++;        push(@X,shift(@X));     # "rotate" X[]
1323 }
1324
1325 sub Xuplast_avx_80()
1326 { use integer;
1327   my $body = shift;
1328   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
1329   my ($a,$b,$c,$d,$e);
1330
1331          eval(shift(@insns));
1332           &vpaddd       (@Tx[1],$Kx,@X[-1&7]);
1333          eval(shift(@insns));
1334          eval(shift(@insns));
1335          eval(shift(@insns));
1336          eval(shift(@insns));
1337
1338           &vmovdqa      (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU
1339
1340          foreach (@insns) { eval; }             # remaining instructions
1341
1342         &cmp    ($inp,$len);
1343         &je     (shift);
1344
1345         &vmovdqa(@Tx[1],"64($K_XX_XX)");        # pbswap mask
1346         &vmovdqa($Kx,"0($K_XX_XX)");            # K_00_19
1347         &vmovdqu(@X[-4&7],"0($inp)");           # load input
1348         &vmovdqu(@X[-3&7],"16($inp)");
1349         &vmovdqu(@X[-2&7],"32($inp)");
1350         &vmovdqu(@X[-1&7],"48($inp)");
1351         &vpshufb(@X[-4&7],@X[-4&7],@Tx[1]);     # byte swap
1352         &add    ($inp,64);
1353
1354   $Xi=0;
1355 }
1356
1357 sub Xloop_avx()
1358 { use integer;
1359   my $body = shift;
1360   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
1361   my ($a,$b,$c,$d,$e);
1362
1363          eval(shift(@insns));
1364          eval(shift(@insns));
1365         &vpshufb(@X[($Xi-3)&7],@X[($Xi-3)&7],@Tx[1]);
1366          eval(shift(@insns));
1367          eval(shift(@insns));
1368         &vpaddd (@Tx[0],@X[($Xi-4)&7],$Kx);
1369          eval(shift(@insns));
1370          eval(shift(@insns));
1371          eval(shift(@insns));
1372          eval(shift(@insns));
1373         &vmovdqa(eval(16*$Xi)."(%rsp)",@Tx[0]); # X[]+K xfer to IALU
1374          eval(shift(@insns));
1375          eval(shift(@insns));
1376
1377         foreach (@insns) { eval; }
1378   $Xi++;
1379 }
1380
1381 sub Xtail_avx()
1382 { use integer;
1383   my $body = shift;
1384   my @insns = (&$body,&$body,&$body,&$body);    # 32 instructions
1385   my ($a,$b,$c,$d,$e);
1386
1387         foreach (@insns) { eval; }
1388 }
1389
1390 $code.=<<___;
1391 .align  32
1392 .Loop_avx:
1393 ___
1394         &Xupdate_avx_16_31(\&body_00_19);
1395         &Xupdate_avx_16_31(\&body_00_19);
1396         &Xupdate_avx_16_31(\&body_00_19);
1397         &Xupdate_avx_16_31(\&body_00_19);
1398         &Xupdate_avx_32_79(\&body_00_19);
1399         &Xupdate_avx_32_79(\&body_20_39);
1400         &Xupdate_avx_32_79(\&body_20_39);
1401         &Xupdate_avx_32_79(\&body_20_39);
1402         &Xupdate_avx_32_79(\&body_20_39);
1403         &Xupdate_avx_32_79(\&body_20_39);
1404         &Xupdate_avx_32_79(\&body_40_59);
1405         &Xupdate_avx_32_79(\&body_40_59);
1406         &Xupdate_avx_32_79(\&body_40_59);
1407         &Xupdate_avx_32_79(\&body_40_59);
1408         &Xupdate_avx_32_79(\&body_40_59);
1409         &Xupdate_avx_32_79(\&body_20_39);
1410         &Xuplast_avx_80(\&body_20_39,".Ldone_avx");     # can jump to "done"
1411
1412                                 $saved_j=$j; @saved_V=@V;
1413                                 $saved_r=$r; @saved_rndkey=@rndkey;
1414
1415         &Xloop_avx(\&body_20_39);
1416         &Xloop_avx(\&body_20_39);
1417         &Xloop_avx(\&body_20_39);
1418
1419 $code.=<<___;
1420         vmovups $iv,48($out,$in0)               # write output
1421         lea     64($in0),$in0
1422
1423         add     0($ctx),$A                      # update context
1424         add     4($ctx),@T[0]
1425         add     8($ctx),$C
1426         add     12($ctx),$D
1427         mov     $A,0($ctx)
1428         add     16($ctx),$E
1429         mov     @T[0],4($ctx)
1430         mov     @T[0],$B                        # magic seed
1431         mov     $C,8($ctx)
1432         mov     $C,@T[1]
1433         mov     $D,12($ctx)
1434         xor     $D,@T[1]
1435         mov     $E,16($ctx)
1436         and     @T[1],@T[0]
1437         jmp     .Loop_avx
1438
1439 .Ldone_avx:
1440 ___
1441                                 $jj=$j=$saved_j; @V=@saved_V;
1442                                 $r=$saved_r;     @rndkey=@saved_rndkey;
1443
1444         &Xtail_avx(\&body_20_39);
1445         &Xtail_avx(\&body_20_39);
1446         &Xtail_avx(\&body_20_39);
1447
1448 $code.=<<___;
1449         vmovups $iv,48($out,$in0)               # write output
1450         mov     88(%rsp),$ivp                   # restore $ivp
1451
1452         add     0($ctx),$A                      # update context
1453         add     4($ctx),@T[0]
1454         add     8($ctx),$C
1455         mov     $A,0($ctx)
1456         add     12($ctx),$D
1457         mov     @T[0],4($ctx)
1458         add     16($ctx),$E
1459         mov     $C,8($ctx)
1460         mov     $D,12($ctx)
1461         mov     $E,16($ctx)
1462         vmovups $iv,($ivp)                      # write IV
1463         vzeroall
1464 ___
1465 $code.=<<___ if ($win64);
1466         movaps  96+0(%rsp),%xmm6
1467         movaps  96+16(%rsp),%xmm7
1468         movaps  96+32(%rsp),%xmm8
1469         movaps  96+48(%rsp),%xmm9
1470         movaps  96+64(%rsp),%xmm10
1471         movaps  96+80(%rsp),%xmm11
1472         movaps  96+96(%rsp),%xmm12
1473         movaps  96+112(%rsp),%xmm13
1474         movaps  96+128(%rsp),%xmm14
1475         movaps  96+144(%rsp),%xmm15
1476 ___
1477 $code.=<<___;
1478         lea     `104+($win64?10*16:0)`(%rsp),%rsi
1479 .cfi_def_cfa    %rsi,56
1480         mov     0(%rsi),%r15
1481 .cfi_restore    %r15
1482         mov     8(%rsi),%r14
1483 .cfi_restore    %r14
1484         mov     16(%rsi),%r13
1485 .cfi_restore    %r13
1486         mov     24(%rsi),%r12
1487 .cfi_restore    %r12
1488         mov     32(%rsi),%rbp
1489 .cfi_restore    %rbp
1490         mov     40(%rsi),%rbx
1491 .cfi_restore    %rbx
1492         lea     48(%rsi),%rsp
1493 .cfi_def_cfa    %rsp,8
1494 .Lepilogue_avx:
1495         ret
1496 .cfi_endproc
1497 .size   aesni_cbc_sha1_enc_avx,.-aesni_cbc_sha1_enc_avx
1498 ___
1499
1500                                                 if ($stitched_decrypt) {{{
1501 # reset
1502 ($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10");
1503
1504 $j=$jj=$r=$rx=0;
1505 $Xi=4;
1506
1507 @aes256_dec = (
1508         '&vpxor ($inout0,$rndkey0,"0x00($in0)");',
1509         '&vpxor ($inout1,$rndkey0,"0x10($in0)");',
1510         '&vpxor ($inout2,$rndkey0,"0x20($in0)");',
1511         '&vpxor ($inout3,$rndkey0,"0x30($in0)");',
1512
1513         '&vmovups($rndkey0,"16-112($key)");',
1514         '&vmovups("64(%rsp)",@X[2]);',          # save IV, originally @X[3]
1515         undef,undef
1516         );
1517 for ($i=0;$i<13;$i++) {
1518     push (@aes256_dec,(
1519         '&vaesdec       ($inout0,$inout0,$rndkey0);',
1520         '&vaesdec       ($inout1,$inout1,$rndkey0);',
1521         '&vaesdec       ($inout2,$inout2,$rndkey0);',
1522         '&vaesdec       ($inout3,$inout3,$rndkey0);     &vmovups($rndkey0,"'.(16*($i+2)-112).'($key)");'
1523         ));
1524     push (@aes256_dec,(undef,undef))    if (($i>=3 && $i<=5) || $i>=11);
1525     push (@aes256_dec,(undef,undef))    if ($i==5);
1526 }
1527 push(@aes256_dec,(
1528         '&vaesdeclast   ($inout0,$inout0,$rndkey0);     &vmovups(@X[0],"0x00($in0)");',
1529         '&vaesdeclast   ($inout1,$inout1,$rndkey0);     &vmovups(@X[1],"0x10($in0)");',
1530         '&vaesdeclast   ($inout2,$inout2,$rndkey0);     &vmovups(@X[2],"0x20($in0)");',
1531         '&vaesdeclast   ($inout3,$inout3,$rndkey0);     &vmovups(@X[3],"0x30($in0)");',
1532
1533         '&vxorps        ($inout0,$inout0,"64(%rsp)");   &vmovdqu($rndkey0,"-112($key)");',
1534         '&vxorps        ($inout1,$inout1,@X[0]);        &vmovups("0x00($out,$in0)",$inout0);',
1535         '&vxorps        ($inout2,$inout2,@X[1]);        &vmovups("0x10($out,$in0)",$inout1);',
1536         '&vxorps        ($inout3,$inout3,@X[2]);        &vmovups("0x20($out,$in0)",$inout2);',
1537
1538         '&vmovups       ("0x30($out,$in0)",$inout3);'
1539         ));
1540
1541 $code.=<<___;
1542 .type   aesni256_cbc_sha1_dec_avx,\@function,6
1543 .align  32
1544 aesni256_cbc_sha1_dec_avx:
1545 .cfi_startproc
1546         mov     `($win64?56:8)`(%rsp),$inp      # load 7th argument
1547         push    %rbx
1548 .cfi_push       %rbx
1549         push    %rbp
1550 .cfi_push       %rbp
1551         push    %r12
1552 .cfi_push       %r12
1553         push    %r13
1554 .cfi_push       %r13
1555         push    %r14
1556 .cfi_push       %r14
1557         push    %r15
1558 .cfi_push       %r15
1559         lea     `-104-($win64?10*16:0)`(%rsp),%rsp
1560 .cfi_adjust_cfa_offset  `104+($win64?10*16:0)`
1561 ___
1562 $code.=<<___ if ($win64);
1563         movaps  %xmm6,96+0(%rsp)
1564         movaps  %xmm7,96+16(%rsp)
1565         movaps  %xmm8,96+32(%rsp)
1566         movaps  %xmm9,96+48(%rsp)
1567         movaps  %xmm10,96+64(%rsp)
1568         movaps  %xmm11,96+80(%rsp)
1569         movaps  %xmm12,96+96(%rsp)
1570         movaps  %xmm13,96+112(%rsp)
1571         movaps  %xmm14,96+128(%rsp)
1572         movaps  %xmm15,96+144(%rsp)
1573 .Lprologue_dec_avx:
1574 ___
1575 $code.=<<___;
1576         vzeroall
1577         mov     $in0,%r12                       # reassign arguments
1578         mov     $out,%r13
1579         mov     $len,%r14
1580         lea     112($key),%r15                  # size optimization
1581         vmovdqu ($ivp),@X[3]                    # load IV
1582 ___
1583 ($in0,$out,$len,$key)=map("%r$_",(12..15));     # reassign arguments
1584 $code.=<<___;
1585         shl     \$6,$len
1586         sub     $in0,$out
1587         add     $inp,$len               # end of input
1588
1589         lea     K_XX_XX(%rip),$K_XX_XX
1590         mov     0($ctx),$A              # load context
1591         mov     4($ctx),$B
1592         mov     8($ctx),$C
1593         mov     12($ctx),$D
1594         mov     $B,@T[0]                # magic seed
1595         mov     16($ctx),$E
1596         mov     $C,@T[1]
1597         xor     $D,@T[1]
1598         and     @T[1],@T[0]
1599
1600         vmovdqa 64($K_XX_XX),@X[2]      # pbswap mask
1601         vmovdqa 0($K_XX_XX),$Kx         # K_00_19
1602         vmovdqu 0($inp),@X[-4&7]        # load input to %xmm[0-3]
1603         vmovdqu 16($inp),@X[-3&7]
1604         vmovdqu 32($inp),@X[-2&7]
1605         vmovdqu 48($inp),@X[-1&7]
1606         vpshufb @X[2],@X[-4&7],@X[-4&7] # byte swap
1607         add     \$64,$inp
1608         vpshufb @X[2],@X[-3&7],@X[-3&7]
1609         vpshufb @X[2],@X[-2&7],@X[-2&7]
1610         vpshufb @X[2],@X[-1&7],@X[-1&7]
1611         vpaddd  $Kx,@X[-4&7],@X[0]      # add K_00_19
1612         vpaddd  $Kx,@X[-3&7],@X[1]
1613         vpaddd  $Kx,@X[-2&7],@X[2]
1614         vmovdqa @X[0],0(%rsp)           # X[]+K xfer to IALU
1615         vmovdqa @X[1],16(%rsp)
1616         vmovdqa @X[2],32(%rsp)
1617         vmovups -112($key),$rndkey0     # $key[0]
1618         jmp     .Loop_dec_avx
1619
1620 .align  32
1621 .Loop_dec_avx:
1622 ___
1623         &Xupdate_avx_16_31(\&body_00_19_dec);
1624         &Xupdate_avx_16_31(\&body_00_19_dec);
1625         &Xupdate_avx_16_31(\&body_00_19_dec);
1626         &Xupdate_avx_16_31(\&body_00_19_dec);
1627         &Xupdate_avx_32_79(\&body_00_19_dec);
1628         &Xupdate_avx_32_79(\&body_20_39_dec);
1629         &Xupdate_avx_32_79(\&body_20_39_dec);
1630         &Xupdate_avx_32_79(\&body_20_39_dec);
1631         &Xupdate_avx_32_79(\&body_20_39_dec);
1632         &Xupdate_avx_32_79(\&body_20_39_dec);
1633         &Xupdate_avx_32_79(\&body_40_59_dec);
1634         &Xupdate_avx_32_79(\&body_40_59_dec);
1635         &Xupdate_avx_32_79(\&body_40_59_dec);
1636         &Xupdate_avx_32_79(\&body_40_59_dec);
1637         &Xupdate_avx_32_79(\&body_40_59_dec);
1638         &Xupdate_avx_32_79(\&body_20_39_dec);
1639         &Xuplast_avx_80(\&body_20_39_dec,".Ldone_dec_avx");     # can jump to "done"
1640
1641                                 $saved_j=$j; @saved_V=@V;
1642                                 $saved_rx=$rx;
1643
1644         &Xloop_avx(\&body_20_39_dec);
1645         &Xloop_avx(\&body_20_39_dec);
1646         &Xloop_avx(\&body_20_39_dec);
1647
1648         eval(@aes256_dec[-1]);                  # last store
1649 $code.=<<___;
1650         lea     64($in0),$in0
1651
1652         add     0($ctx),$A                      # update context
1653         add     4($ctx),@T[0]
1654         add     8($ctx),$C
1655         add     12($ctx),$D
1656         mov     $A,0($ctx)
1657         add     16($ctx),$E
1658         mov     @T[0],4($ctx)
1659         mov     @T[0],$B                        # magic seed
1660         mov     $C,8($ctx)
1661         mov     $C,@T[1]
1662         mov     $D,12($ctx)
1663         xor     $D,@T[1]
1664         mov     $E,16($ctx)
1665         and     @T[1],@T[0]
1666         jmp     .Loop_dec_avx
1667
1668 .Ldone_dec_avx:
1669 ___
1670                                 $jj=$j=$saved_j; @V=@saved_V;
1671                                 $rx=$saved_rx;
1672
1673         &Xtail_avx(\&body_20_39_dec);
1674         &Xtail_avx(\&body_20_39_dec);
1675         &Xtail_avx(\&body_20_39_dec);
1676
1677         eval(@aes256_dec[-1]);                  # last store
1678 $code.=<<___;
1679
1680         add     0($ctx),$A                      # update context
1681         add     4($ctx),@T[0]
1682         add     8($ctx),$C
1683         mov     $A,0($ctx)
1684         add     12($ctx),$D
1685         mov     @T[0],4($ctx)
1686         add     16($ctx),$E
1687         mov     $C,8($ctx)
1688         mov     $D,12($ctx)
1689         mov     $E,16($ctx)
1690         vmovups @X[3],($ivp)                    # write IV
1691         vzeroall
1692 ___
1693 $code.=<<___ if ($win64);
1694         movaps  96+0(%rsp),%xmm6
1695         movaps  96+16(%rsp),%xmm7
1696         movaps  96+32(%rsp),%xmm8
1697         movaps  96+48(%rsp),%xmm9
1698         movaps  96+64(%rsp),%xmm10
1699         movaps  96+80(%rsp),%xmm11
1700         movaps  96+96(%rsp),%xmm12
1701         movaps  96+112(%rsp),%xmm13
1702         movaps  96+128(%rsp),%xmm14
1703         movaps  96+144(%rsp),%xmm15
1704 ___
1705 $code.=<<___;
1706         lea     `104+($win64?10*16:0)`(%rsp),%rsi
1707 .cfi_def_cfa    %rsi,56
1708         mov     0(%rsi),%r15
1709 .cfi_restore    %r15
1710         mov     8(%rsi),%r14
1711 .cfi_restore    %r14
1712         mov     16(%rsi),%r13
1713 .cfi_restore    %r13
1714         mov     24(%rsi),%r12
1715 .cfi_restore    %r12
1716         mov     32(%rsi),%rbp
1717 .cfi_restore    %rbp
1718         mov     40(%rsi),%rbx
1719 .cfi_restore    %rbx
1720         lea     48(%rsi),%rsp
1721 .cfi_def_cfa    %rsp,8
1722 .Lepilogue_dec_avx:
1723         ret
1724 .cfi_endproc
1725 .size   aesni256_cbc_sha1_dec_avx,.-aesni256_cbc_sha1_dec_avx
1726 ___
1727                                                 }}}
1728 }
1729 $code.=<<___;
1730 .align  64
1731 K_XX_XX:
1732 .long   0x5a827999,0x5a827999,0x5a827999,0x5a827999     # K_00_19
1733 .long   0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1     # K_20_39
1734 .long   0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc     # K_40_59
1735 .long   0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6     # K_60_79
1736 .long   0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f     # pbswap mask
1737 .byte   0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0
1738
1739 .asciz  "AESNI-CBC+SHA1 stitch for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
1740 .align  64
1741 ___
1742                                                 if ($shaext) {{{
1743 ($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10");
1744
1745 $rounds="%r11d";
1746
1747 ($iv,$in,$rndkey0)=map("%xmm$_",(2,14,15));
1748 @rndkey=("%xmm0","%xmm1");
1749 $r=0;
1750
1751 my ($BSWAP,$ABCD,$E,$E_,$ABCD_SAVE,$E_SAVE)=map("%xmm$_",(7..12));
1752 my @MSG=map("%xmm$_",(3..6));
1753
1754 $code.=<<___;
1755 .type   aesni_cbc_sha1_enc_shaext,\@function,6
1756 .align  32
1757 aesni_cbc_sha1_enc_shaext:
1758         mov     `($win64?56:8)`(%rsp),$inp      # load 7th argument
1759 ___
1760 $code.=<<___ if ($win64);
1761         lea     `-8-10*16`(%rsp),%rsp
1762         movaps  %xmm6,-8-10*16(%rax)
1763         movaps  %xmm7,-8-9*16(%rax)
1764         movaps  %xmm8,-8-8*16(%rax)
1765         movaps  %xmm9,-8-7*16(%rax)
1766         movaps  %xmm10,-8-6*16(%rax)
1767         movaps  %xmm11,-8-5*16(%rax)
1768         movaps  %xmm12,-8-4*16(%rax)
1769         movaps  %xmm13,-8-3*16(%rax)
1770         movaps  %xmm14,-8-2*16(%rax)
1771         movaps  %xmm15,-8-1*16(%rax)
1772 .Lprologue_shaext:
1773 ___
1774 $code.=<<___;
1775         movdqu  ($ctx),$ABCD
1776         movd    16($ctx),$E
1777         movdqa  K_XX_XX+0x50(%rip),$BSWAP       # byte-n-word swap
1778
1779         mov     240($key),$rounds
1780         sub     $in0,$out
1781         movups  ($key),$rndkey0                 # $key[0]
1782         movups  ($ivp),$iv                      # load IV
1783         movups  16($key),$rndkey[0]             # forward reference
1784         lea     112($key),$key                  # size optimization
1785
1786         pshufd  \$0b00011011,$ABCD,$ABCD        # flip word order
1787         pshufd  \$0b00011011,$E,$E              # flip word order
1788         jmp     .Loop_shaext
1789
1790 .align  16
1791 .Loop_shaext:
1792 ___
1793         &$aesenc();
1794 $code.=<<___;
1795         movdqu          ($inp),@MSG[0]
1796         movdqa          $E,$E_SAVE              # offload $E
1797         pshufb          $BSWAP,@MSG[0]
1798         movdqu          0x10($inp),@MSG[1]
1799         movdqa          $ABCD,$ABCD_SAVE        # offload $ABCD
1800 ___
1801         &$aesenc();
1802 $code.=<<___;
1803         pshufb          $BSWAP,@MSG[1]
1804
1805         paddd           @MSG[0],$E
1806         movdqu          0x20($inp),@MSG[2]
1807         lea             0x40($inp),$inp
1808         pxor            $E_SAVE,@MSG[0]         # black magic
1809 ___
1810         &$aesenc();
1811 $code.=<<___;
1812         pxor            $E_SAVE,@MSG[0]         # black magic
1813         movdqa          $ABCD,$E_
1814         pshufb          $BSWAP,@MSG[2]
1815         sha1rnds4       \$0,$E,$ABCD            # 0-3
1816         sha1nexte       @MSG[1],$E_
1817 ___
1818         &$aesenc();
1819 $code.=<<___;
1820         sha1msg1        @MSG[1],@MSG[0]
1821         movdqu          -0x10($inp),@MSG[3]
1822         movdqa          $ABCD,$E
1823         pshufb          $BSWAP,@MSG[3]
1824 ___
1825         &$aesenc();
1826 $code.=<<___;
1827         sha1rnds4       \$0,$E_,$ABCD           # 4-7
1828         sha1nexte       @MSG[2],$E
1829         pxor            @MSG[2],@MSG[0]
1830         sha1msg1        @MSG[2],@MSG[1]
1831 ___
1832         &$aesenc();
1833
1834 for($i=2;$i<20-4;$i++) {
1835 $code.=<<___;
1836         movdqa          $ABCD,$E_
1837         sha1rnds4       \$`int($i/5)`,$E,$ABCD  # 8-11
1838         sha1nexte       @MSG[3],$E_
1839 ___
1840         &$aesenc();
1841 $code.=<<___;
1842         sha1msg2        @MSG[3],@MSG[0]
1843         pxor            @MSG[3],@MSG[1]
1844         sha1msg1        @MSG[3],@MSG[2]
1845 ___
1846         ($E,$E_)=($E_,$E);
1847         push(@MSG,shift(@MSG));
1848
1849         &$aesenc();
1850 }
1851 $code.=<<___;
1852         movdqa          $ABCD,$E_
1853         sha1rnds4       \$3,$E,$ABCD            # 64-67
1854         sha1nexte       @MSG[3],$E_
1855         sha1msg2        @MSG[3],@MSG[0]
1856         pxor            @MSG[3],@MSG[1]
1857 ___
1858         &$aesenc();
1859 $code.=<<___;
1860         movdqa          $ABCD,$E
1861         sha1rnds4       \$3,$E_,$ABCD           # 68-71
1862         sha1nexte       @MSG[0],$E
1863         sha1msg2        @MSG[0],@MSG[1]
1864 ___
1865         &$aesenc();
1866 $code.=<<___;
1867         movdqa          $E_SAVE,@MSG[0]
1868         movdqa          $ABCD,$E_
1869         sha1rnds4       \$3,$E,$ABCD            # 72-75
1870         sha1nexte       @MSG[1],$E_
1871 ___
1872         &$aesenc();
1873 $code.=<<___;
1874         movdqa          $ABCD,$E
1875         sha1rnds4       \$3,$E_,$ABCD           # 76-79
1876         sha1nexte       $MSG[0],$E
1877 ___
1878         while($r<40)    { &$aesenc(); }         # remaining aesenc's
1879 $code.=<<___;
1880         dec             $len
1881
1882         paddd           $ABCD_SAVE,$ABCD
1883         movups          $iv,48($out,$in0)       # write output
1884         lea             64($in0),$in0
1885         jnz             .Loop_shaext
1886
1887         pshufd  \$0b00011011,$ABCD,$ABCD
1888         pshufd  \$0b00011011,$E,$E
1889         movups  $iv,($ivp)                      # write IV
1890         movdqu  $ABCD,($ctx)
1891         movd    $E,16($ctx)
1892 ___
1893 $code.=<<___ if ($win64);
1894         movaps  -8-10*16(%rax),%xmm6
1895         movaps  -8-9*16(%rax),%xmm7
1896         movaps  -8-8*16(%rax),%xmm8
1897         movaps  -8-7*16(%rax),%xmm9
1898         movaps  -8-6*16(%rax),%xmm10
1899         movaps  -8-5*16(%rax),%xmm11
1900         movaps  -8-4*16(%rax),%xmm12
1901         movaps  -8-3*16(%rax),%xmm13
1902         movaps  -8-2*16(%rax),%xmm14
1903         movaps  -8-1*16(%rax),%xmm15
1904         mov     %rax,%rsp
1905 .Lepilogue_shaext:
1906 ___
1907 $code.=<<___;
1908         ret
1909 .size   aesni_cbc_sha1_enc_shaext,.-aesni_cbc_sha1_enc_shaext
1910 ___
1911                                                 }}}
1912 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
1913 #               CONTEXT *context,DISPATCHER_CONTEXT *disp)
1914 if ($win64) {
1915 $rec="%rcx";
1916 $frame="%rdx";
1917 $context="%r8";
1918 $disp="%r9";
1919
1920 $code.=<<___;
1921 .extern __imp_RtlVirtualUnwind
1922 .type   ssse3_handler,\@abi-omnipotent
1923 .align  16
1924 ssse3_handler:
1925         push    %rsi
1926         push    %rdi
1927         push    %rbx
1928         push    %rbp
1929         push    %r12
1930         push    %r13
1931         push    %r14
1932         push    %r15
1933         pushfq
1934         sub     \$64,%rsp
1935
1936         mov     120($context),%rax      # pull context->Rax
1937         mov     248($context),%rbx      # pull context->Rip
1938
1939         mov     8($disp),%rsi           # disp->ImageBase
1940         mov     56($disp),%r11          # disp->HandlerData
1941
1942         mov     0(%r11),%r10d           # HandlerData[0]
1943         lea     (%rsi,%r10),%r10        # prologue label
1944         cmp     %r10,%rbx               # context->Rip<prologue label
1945         jb      .Lcommon_seh_tail
1946
1947         mov     152($context),%rax      # pull context->Rsp
1948
1949         mov     4(%r11),%r10d           # HandlerData[1]
1950         lea     (%rsi,%r10),%r10        # epilogue label
1951         cmp     %r10,%rbx               # context->Rip>=epilogue label
1952         jae     .Lcommon_seh_tail
1953 ___
1954 $code.=<<___ if ($shaext);
1955         lea     aesni_cbc_sha1_enc_shaext(%rip),%r10
1956         cmp     %r10,%rbx
1957         jb      .Lseh_no_shaext
1958
1959         lea     (%rax),%rsi
1960         lea     512($context),%rdi      # &context.Xmm6
1961         mov     \$20,%ecx
1962         .long   0xa548f3fc              # cld; rep movsq
1963         lea     168(%rax),%rax          # adjust stack pointer
1964         jmp     .Lcommon_seh_tail
1965 .Lseh_no_shaext:
1966 ___
1967 $code.=<<___;
1968         lea     96(%rax),%rsi
1969         lea     512($context),%rdi      # &context.Xmm6
1970         mov     \$20,%ecx
1971         .long   0xa548f3fc              # cld; rep movsq
1972         lea     `104+10*16`(%rax),%rax  # adjust stack pointer
1973
1974         mov     0(%rax),%r15
1975         mov     8(%rax),%r14
1976         mov     16(%rax),%r13
1977         mov     24(%rax),%r12
1978         mov     32(%rax),%rbp
1979         mov     40(%rax),%rbx
1980         lea     48(%rax),%rax
1981         mov     %rbx,144($context)      # restore context->Rbx
1982         mov     %rbp,160($context)      # restore context->Rbp
1983         mov     %r12,216($context)      # restore context->R12
1984         mov     %r13,224($context)      # restore context->R13
1985         mov     %r14,232($context)      # restore context->R14
1986         mov     %r15,240($context)      # restore context->R15
1987
1988 .Lcommon_seh_tail:
1989         mov     8(%rax),%rdi
1990         mov     16(%rax),%rsi
1991         mov     %rax,152($context)      # restore context->Rsp
1992         mov     %rsi,168($context)      # restore context->Rsi
1993         mov     %rdi,176($context)      # restore context->Rdi
1994
1995         mov     40($disp),%rdi          # disp->ContextRecord
1996         mov     $context,%rsi           # context
1997         mov     \$154,%ecx              # sizeof(CONTEXT)
1998         .long   0xa548f3fc              # cld; rep movsq
1999
2000         mov     $disp,%rsi
2001         xor     %rcx,%rcx               # arg1, UNW_FLAG_NHANDLER
2002         mov     8(%rsi),%rdx            # arg2, disp->ImageBase
2003         mov     0(%rsi),%r8             # arg3, disp->ControlPc
2004         mov     16(%rsi),%r9            # arg4, disp->FunctionEntry
2005         mov     40(%rsi),%r10           # disp->ContextRecord
2006         lea     56(%rsi),%r11           # &disp->HandlerData
2007         lea     24(%rsi),%r12           # &disp->EstablisherFrame
2008         mov     %r10,32(%rsp)           # arg5
2009         mov     %r11,40(%rsp)           # arg6
2010         mov     %r12,48(%rsp)           # arg7
2011         mov     %rcx,56(%rsp)           # arg8, (NULL)
2012         call    *__imp_RtlVirtualUnwind(%rip)
2013
2014         mov     \$1,%eax                # ExceptionContinueSearch
2015         add     \$64,%rsp
2016         popfq
2017         pop     %r15
2018         pop     %r14
2019         pop     %r13
2020         pop     %r12
2021         pop     %rbp
2022         pop     %rbx
2023         pop     %rdi
2024         pop     %rsi
2025         ret
2026 .size   ssse3_handler,.-ssse3_handler
2027
2028 .section        .pdata
2029 .align  4
2030         .rva    .LSEH_begin_aesni_cbc_sha1_enc_ssse3
2031         .rva    .LSEH_end_aesni_cbc_sha1_enc_ssse3
2032         .rva    .LSEH_info_aesni_cbc_sha1_enc_ssse3
2033 ___
2034 $code.=<<___ if ($avx);
2035         .rva    .LSEH_begin_aesni_cbc_sha1_enc_avx
2036         .rva    .LSEH_end_aesni_cbc_sha1_enc_avx
2037         .rva    .LSEH_info_aesni_cbc_sha1_enc_avx
2038 ___
2039 $code.=<<___ if ($shaext);
2040         .rva    .LSEH_begin_aesni_cbc_sha1_enc_shaext
2041         .rva    .LSEH_end_aesni_cbc_sha1_enc_shaext
2042         .rva    .LSEH_info_aesni_cbc_sha1_enc_shaext
2043 ___
2044 $code.=<<___;
2045 .section        .xdata
2046 .align  8
2047 .LSEH_info_aesni_cbc_sha1_enc_ssse3:
2048         .byte   9,0,0,0
2049         .rva    ssse3_handler
2050         .rva    .Lprologue_ssse3,.Lepilogue_ssse3       # HandlerData[]
2051 ___
2052 $code.=<<___ if ($avx);
2053 .LSEH_info_aesni_cbc_sha1_enc_avx:
2054         .byte   9,0,0,0
2055         .rva    ssse3_handler
2056         .rva    .Lprologue_avx,.Lepilogue_avx           # HandlerData[]
2057 ___
2058 $code.=<<___ if ($shaext);
2059 .LSEH_info_aesni_cbc_sha1_enc_shaext:
2060         .byte   9,0,0,0
2061         .rva    ssse3_handler
2062         .rva    .Lprologue_shaext,.Lepilogue_shaext     # HandlerData[]
2063 ___
2064 }
2065
2066 ####################################################################
2067 sub rex {
2068   local *opcode=shift;
2069   my ($dst,$src)=@_;
2070   my $rex=0;
2071
2072     $rex|=0x04                  if($dst>=8);
2073     $rex|=0x01                  if($src>=8);
2074     unshift @opcode,$rex|0x40   if($rex);
2075 }
2076
2077 sub sha1rnds4 {
2078     if (@_[0] =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
2079       my @opcode=(0x0f,0x3a,0xcc);
2080         rex(\@opcode,$3,$2);
2081         push @opcode,0xc0|($2&7)|(($3&7)<<3);           # ModR/M
2082         my $c=$1;
2083         push @opcode,$c=~/^0/?oct($c):$c;
2084         return ".byte\t".join(',',@opcode);
2085     } else {
2086         return "sha1rnds4\t".@_[0];
2087     }
2088 }
2089
2090 sub sha1op38 {
2091     my $instr = shift;
2092     my %opcodelet = (
2093                 "sha1nexte" => 0xc8,
2094                 "sha1msg1"  => 0xc9,
2095                 "sha1msg2"  => 0xca     );
2096
2097     if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) {
2098       my @opcode=(0x0f,0x38);
2099         rex(\@opcode,$2,$1);
2100         push @opcode,$opcodelet{$instr};
2101         push @opcode,0xc0|($1&7)|(($2&7)<<3);           # ModR/M
2102         return ".byte\t".join(',',@opcode);
2103     } else {
2104         return $instr."\t".@_[0];
2105     }
2106 }
2107
2108 sub aesni {
2109   my $line=shift;
2110   my @opcode=(0x0f,0x38);
2111
2112     if ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) {
2113         my %opcodelet = (
2114                 "aesenc" => 0xdc,       "aesenclast" => 0xdd,
2115                 "aesdec" => 0xde,       "aesdeclast" => 0xdf
2116         );
2117         return undef if (!defined($opcodelet{$1}));
2118         rex(\@opcode,$3,$2);
2119         push @opcode,$opcodelet{$1},0xc0|($2&7)|(($3&7)<<3);    # ModR/M
2120         unshift @opcode,0x66;
2121         return ".byte\t".join(',',@opcode);
2122     }
2123     return $line;
2124 }
2125
2126 foreach (split("\n",$code)) {
2127         s/\`([^\`]*)\`/eval $1/geo;
2128
2129         s/\b(sha1rnds4)\s+(.*)/sha1rnds4($2)/geo                or
2130         s/\b(sha1[^\s]*)\s+(.*)/sha1op38($1,$2)/geo             or
2131         s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/geo;
2132
2133         print $_,"\n";
2134 }
2135 close STDOUT;