aesni-x86_64.pl: make it compile on MacOS X.
[openssl.git] / crypto / aes / asm / aesni-x86_64.pl
1 #!/usr/bin/env perl
2 #
3 # ====================================================================
4 # Written by Andy Polyakov <appro@fy.chalmers.se> 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 # This module implements support for Intel AES-NI extension. In
11 # OpenSSL context it's used with Intel engine, but can also be used as
12 # drop-in replacement for crypto/aes/asm/aes-x86_64.pl [see below for
13 # details].
14 #
15 # Performance.
16 #
17 # Given aes(enc|dec) instructions' latency asymptotic performance for
18 # non-parallelizable modes such as CBC encrypt is 3.75 cycles per byte
19 # processed with 128-bit key. And given their throughput asymptotic
20 # performance for parallelizable modes is 1.25 cycles per byte. Being
21 # asymptotic limit is not something you commonly achieve in reality,
22 # but how close does one get? Below are results collected for
23 # different modes and block sized. Pairs of numbers are for en-/
24 # decryption.
25 #
26 #       16-byte     64-byte     256-byte    1-KB        8-KB
27 # ECB   4.25/4.25   1.38/1.38   1.28/1.28   1.26/1.26   1.26/1.26
28 # CTR   5.42/5.42   1.92/1.92   1.44/1.44   1.28/1.28   1.26/1.26
29 # CBC   4.38/4.43   4.15/1.43   4.07/1.32   4.07/1.29   4.06/1.28
30 # CCM   5.66/9.42   4.42/5.41   4.16/4.40   4.09/4.15   4.06/4.07   
31 # OFB   5.42/5.42   4.64/4.64   4.44/4.44   4.39/4.39   4.38/4.38
32 # CFB   5.73/5.85   5.56/5.62   5.48/5.56   5.47/5.55   5.47/5.55
33 #
34 # ECB, CTR, CBC and CCM results are free from EVP overhead. This means
35 # that otherwise used 'openssl speed -evp aes-128-??? -engine aesni
36 # [-decrypt]' will exhibit 10-15% worse results for smaller blocks.
37 # The results were collected with specially crafted speed.c benchmark
38 # in order to compare them with results reported in "Intel Advanced
39 # Encryption Standard (AES) New Instruction Set" White Paper Revision
40 # 3.0 dated May 2010. All above results are consistently better. This
41 # module also provides better performance for block sizes smaller than
42 # 128 bytes in points *not* represented in the above table.
43 #
44 # Looking at the results for 8-KB buffer.
45 #
46 # CFB and OFB results are far from the limit, because implementation
47 # uses "generic" CRYPTO_[c|o]fb128_encrypt interfaces relying on
48 # single-block aesni_encrypt, which is not the most optimal way to go.
49 # CBC encrypt result is unexpectedly high and there is no documented
50 # explanation for it. Seemingly there is a small penalty for feeding
51 # the result back to AES unit the way it's done in CBC mode. There is
52 # nothing one can do and the result appears optimal. CCM result is
53 # identical to CBC, because CBC-MAC is essentially CBC encrypt without
54 # saving output. CCM CTR "stays invisible," because it's neatly
55 # interleaved wih CBC-MAC. This provides ~30% improvement over
56 # "straghtforward" CCM implementation with CTR and CBC-MAC performed
57 # disjointly. Parallelizable modes practically achieve the theoretical
58 # limit.
59 #
60 # Looking at how results vary with buffer size.
61 #
62 # Curves are practically saturated at 1-KB buffer size. In most cases
63 # "256-byte" performance is >95%, and "64-byte" is ~90% of "8-KB" one.
64 # CTR curve doesn't follow this pattern and is "slowest" changing one
65 # with "256-byte" result being 87% of "8-KB." This is because overhead
66 # in CTR mode is most computationally intensive. Small-block CCM
67 # decrypt is slower than encrypt, because first CTR and last CBC-MAC
68 # iterations can't be interleaved.
69 #
70 # Results for 192- and 256-bit keys.
71 #
72 # EVP-free results were observed to scale perfectly with number of
73 # rounds for larger block sizes, i.e. 192-bit result being 10/12 times
74 # lower and 256-bit one - 10/14. Well, in CBC encrypt case differences
75 # are a tad smaller, because the above mentioned penalty biases all
76 # results by same constant value. In similar way function call
77 # overhead affects small-block performance, as well as OFB and CFB
78 # results. Differences are not large, most common coefficients are
79 # 10/11.7 and 10/13.4 (as opposite to 10/12.0 and 10/14.0), but one
80 # observe even 10/11.2 and 10/12.4 (CTR, OFB, CFB)...
81
82 $PREFIX="aesni";        # if $PREFIX is set to "AES", the script
83                         # generates drop-in replacement for
84                         # crypto/aes/asm/aes-x86_64.pl:-)
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 open STDOUT,"| $^X $xlate $flavour $output";
98
99 $movkey = $PREFIX eq "aesni" ? "movaps" : "movups";
100 @_4args=$win64? ("%rcx","%rdx","%r8", "%r9") :  # Win64 order
101                 ("%rdi","%rsi","%rdx","%rcx");  # Unix order
102
103 $code=".text\n";
104
105 $rounds="%eax"; # input to and changed by aesni_[en|de]cryptN !!!
106 # this is natural Unix argument order for public $PREFIX_[ecb|cbc]_encrypt ...
107 $inp="%rdi";
108 $out="%rsi";
109 $len="%rdx";
110 $key="%rcx";    # input to and changed by aesni_[en|de]cryptN !!!
111 $ivp="%r8";     # cbc, ctr, ...
112
113 $rnds_="%r10d"; # backup copy for $rounds
114 $key_="%r11";   # backup copy for $key
115
116 # %xmm register layout
117 $inout0="%xmm0";        $inout1="%xmm1";
118 $inout2="%xmm2";        $inout3="%xmm3";
119 $rndkey0="%xmm4";       $rndkey1="%xmm5";
120
121 $iv="%xmm6";            $in0="%xmm7";   # used in CBC decrypt, CTR, ...
122 $in1="%xmm8";           $in2="%xmm9";
123 \f
124 # Inline version of internal aesni_[en|de]crypt1.
125 #
126 # Why folded loop? Because aes[enc|dec] is slow enough to accommodate
127 # cycles which take care of loop variables...
128 { my $sn;
129 sub aesni_generate1 {
130 my ($p,$key,$rounds,$inout)=@_; $inout=$inout0 if (!defined($inout));
131 ++$sn;
132 $code.=<<___;
133         movdqu  ($key),$rndkey0
134         $movkey 16($key),$rndkey1
135         lea     32($key),$key
136         pxor    $rndkey0,$inout
137 .Loop_${p}1_$sn:
138         aes${p} $rndkey1,$inout
139         dec     $rounds
140         $movkey ($key),$rndkey1
141         lea     16($key),$key
142         jnz     .Loop_${p}1_$sn # loop body is 16 bytes
143         aes${p}last     $rndkey1,$inout
144 ___
145 }}
146 # void $PREFIX_[en|de]crypt (const void *inp,void *out,const AES_KEY *key);
147 #
148 { my ($inp,$out,$key) = @_4args;
149
150 $code.=<<___;
151 .globl  ${PREFIX}_encrypt
152 .type   ${PREFIX}_encrypt,\@abi-omnipotent
153 .align  16
154 ${PREFIX}_encrypt:
155         movdqu  ($inp),$inout0          # load input
156         mov     240($key),$rounds       # pull $rounds
157 ___
158         &aesni_generate1("enc",$key,$rounds);
159 $code.=<<___;
160         movups  $inout0,($out)          # output
161         ret
162 .size   ${PREFIX}_encrypt,.-${PREFIX}_encrypt
163
164 .globl  ${PREFIX}_decrypt
165 .type   ${PREFIX}_decrypt,\@abi-omnipotent
166 .align  16
167 ${PREFIX}_decrypt:
168         movdqu  ($inp),$inout0          # load input
169         mov     240($key),$rounds       # pull $rounds
170 ___
171         &aesni_generate1("dec",$key,$rounds);
172 $code.=<<___;
173         movups  $inout0,($out)          # output
174         ret
175 .size   ${PREFIX}_decrypt, .-${PREFIX}_decrypt
176 ___
177 }
178 \f
179 # _aesni_[en|de]crypt[34] are private interfaces, N denotes interleave
180 # factor. Why 3x subroutine is used in loops? Even though aes[enc|dec]
181 # latency is 6, it turned out that it can be scheduled only every
182 # *second* cycle. Thus 3x interleave is the one providing optimal
183 # utilization, i.e. when subroutine's throughput is virtually same as
184 # of non-interleaved subroutine [for number of input blocks up to 3].
185 # This is why it makes no sense to implement 2x subroutine. As soon
186 # as/if Intel improves throughput by making it possible to schedule
187 # the instructions in question *every* cycles I would have to
188 # implement 6x interleave and use it in loop...
189 sub aesni_generate3 {
190 my $dir=shift;
191 # As already mentioned it takes in $key and $rounds, which are *not*
192 # preserved. $inout[0-2] is cipher/clear text...
193 $code.=<<___;
194 .type   _aesni_${dir}rypt3,\@abi-omnipotent
195 .align  16
196 _aesni_${dir}rypt3:
197         $movkey ($key),$rndkey0
198         shr     \$1,$rounds
199         $movkey 16($key),$rndkey1
200         lea     32($key),$key
201         pxor    $rndkey0,$inout0
202         pxor    $rndkey0,$inout1
203         pxor    $rndkey0,$inout2
204         $movkey         ($key),$rndkey0
205
206 .L${dir}_loop3:
207         aes${dir}       $rndkey1,$inout0
208         aes${dir}       $rndkey1,$inout1
209         dec             $rounds
210         aes${dir}       $rndkey1,$inout2
211         $movkey         16($key),$rndkey1
212         aes${dir}       $rndkey0,$inout0
213         aes${dir}       $rndkey0,$inout1
214         lea             32($key),$key
215         aes${dir}       $rndkey0,$inout2
216         $movkey         ($key),$rndkey0
217         jnz             .L${dir}_loop3
218
219         aes${dir}       $rndkey1,$inout0
220         aes${dir}       $rndkey1,$inout1
221         aes${dir}       $rndkey1,$inout2
222         aes${dir}last   $rndkey0,$inout0
223         aes${dir}last   $rndkey0,$inout1
224         aes${dir}last   $rndkey0,$inout2
225         ret
226 .size   _aesni_${dir}rypt3,.-_aesni_${dir}rypt3
227 ___
228 }
229 # 4x interleave is implemented to improve small block performance,
230 # most notably [and naturally] 4 block by ~30%. One can argue that one
231 # should have implemented 5x as well, but improvement would be <20%,
232 # so it's not worth it...
233 sub aesni_generate4 {
234 my $dir=shift;
235 # As already mentioned it takes in $key and $rounds, which are *not*
236 # preserved. $inout[0-3] is cipher/clear text...
237 $code.=<<___;
238 .type   _aesni_${dir}rypt4,\@abi-omnipotent
239 .align  16
240 _aesni_${dir}rypt4:
241         $movkey ($key),$rndkey0
242         shr     \$1,$rounds
243         $movkey 16($key),$rndkey1
244         lea     32($key),$key
245         pxor    $rndkey0,$inout0
246         pxor    $rndkey0,$inout1
247         pxor    $rndkey0,$inout2
248         pxor    $rndkey0,$inout3
249         $movkey         ($key),$rndkey0
250
251 .L${dir}_loop4:
252         aes${dir}       $rndkey1,$inout0
253         aes${dir}       $rndkey1,$inout1
254         dec             $rounds
255         aes${dir}       $rndkey1,$inout2
256         aes${dir}       $rndkey1,$inout3
257         $movkey         16($key),$rndkey1
258         aes${dir}       $rndkey0,$inout0
259         aes${dir}       $rndkey0,$inout1
260         lea             32($key),$key
261         aes${dir}       $rndkey0,$inout2
262         aes${dir}       $rndkey0,$inout3
263         $movkey         ($key),$rndkey0
264         jnz             .L${dir}_loop4
265
266         aes${dir}       $rndkey1,$inout0
267         aes${dir}       $rndkey1,$inout1
268         aes${dir}       $rndkey1,$inout2
269         aes${dir}       $rndkey1,$inout3
270         aes${dir}last   $rndkey0,$inout0
271         aes${dir}last   $rndkey0,$inout1
272         aes${dir}last   $rndkey0,$inout2
273         aes${dir}last   $rndkey0,$inout3
274         ret
275 .size   _aesni_${dir}rypt4,.-_aesni_${dir}rypt4
276 ___
277 }
278 &aesni_generate3("enc") if ($PREFIX eq "aesni");
279 &aesni_generate3("dec");
280 &aesni_generate4("enc") if ($PREFIX eq "aesni");
281 &aesni_generate4("dec");
282 \f
283 if ($PREFIX eq "aesni") {
284 ########################################################################
285 # void aesni_ecb_encrypt (const void *in, void *out,
286 #                         size_t length, const AES_KEY *key,
287 #                         int enc);
288 $code.=<<___;
289 .globl  aesni_ecb_encrypt
290 .type   aesni_ecb_encrypt,\@function,5
291 .align  16
292 aesni_ecb_encrypt:
293         cmp     \$16,$len               # check length
294         jb      .Lecb_ret
295
296         mov     240($key),$rounds       # pull $rounds
297         and     \$-16,$len
298         mov     $key,$key_              # backup $key
299         mov     $rounds,$rnds_          # backup $rounds
300         test    %r8d,%r8d               # 5th argument
301         jz      .Lecb_decrypt
302 #--------------------------- ECB ENCRYPT ------------------------------#
303         cmp     \$0x40,$len
304         jbe     .Lecb_enc_tail
305         sub     \$0x40,$len
306         jmp     .Lecb_enc_loop3
307 .align 16
308 .Lecb_enc_loop3:
309         movups  ($inp),$inout0
310         movups  0x10($inp),$inout1
311         movups  0x20($inp),$inout2
312         call    _aesni_encrypt3
313         lea     0x30($inp),$inp
314         movups  $inout0,($out)
315         mov     $rnds_,$rounds          # restore $rounds
316         movups  $inout1,0x10($out)
317         mov     $key_,$key              # restore $key
318         movups  $inout2,0x20($out)
319         lea     0x30($out),$out
320         sub     \$0x30,$len
321         ja      .Lecb_enc_loop3
322
323         add     \$0x40,$len
324 .Lecb_enc_tail:
325         movups  ($inp),$inout0
326         cmp     \$0x20,$len
327         jb      .Lecb_enc_one
328         movups  0x10($inp),$inout1
329         je      .Lecb_enc_two
330         movups  0x20($inp),$inout2
331         cmp     \$0x30,$len
332         je      .Lecb_enc_three
333         movups  0x30($inp),$inout3
334         call    _aesni_encrypt4
335         movups  $inout0,($out)
336         movups  $inout1,0x10($out)
337         movups  $inout2,0x20($out)
338         movups  $inout3,0x30($out)
339         jmp     .Lecb_ret
340 .align  16
341 .Lecb_enc_one:
342 ___
343         &aesni_generate1("enc",$key,$rounds);
344 $code.=<<___;
345         movups  $inout0,($out)
346         jmp     .Lecb_ret
347 .align  16
348 .Lecb_enc_two:
349         pxor    $inout2,$inout2
350         call    _aesni_encrypt3
351         movups  $inout0,($out)
352         movups  $inout1,0x10($out)
353         jmp     .Lecb_ret
354 .align  16
355 .Lecb_enc_three:
356         call    _aesni_encrypt3
357         movups  $inout0,($out)
358         movups  $inout1,0x10($out)
359         movups  $inout2,0x20($out)
360         jmp     .Lecb_ret
361 \f#--------------------------- ECB DECRYPT ------------------------------#
362 .align  16
363 .Lecb_decrypt:
364         cmp     \$0x40,$len
365         jbe     .Lecb_dec_tail
366         sub     \$0x40,$len
367         jmp     .Lecb_dec_loop3
368 .align 16
369 .Lecb_dec_loop3:
370         movups  ($inp),$inout0
371         movups  0x10($inp),$inout1
372         movups  0x20($inp),$inout2
373         call    _aesni_decrypt3
374         lea     0x30($inp),$inp
375         movups  $inout0,($out)
376         mov     $rnds_,$rounds          # restore $rounds
377         movups  $inout1,0x10($out)
378         mov     $key_,$key              # restore $key
379         movups  $inout2,0x20($out)
380         lea     0x30($out),$out
381         sub     \$0x30,$len
382         ja      .Lecb_dec_loop3
383
384         add     \$0x40,$len
385 .Lecb_dec_tail:
386         movups  ($inp),$inout0
387         cmp     \$0x20,$len
388         jb      .Lecb_dec_one
389         movups  0x10($inp),$inout1
390         je      .Lecb_dec_two
391         movups  0x20($inp),$inout2
392         cmp     \$0x30,$len
393         je      .Lecb_dec_three
394         movups  0x30($inp),$inout3
395         call    _aesni_decrypt4
396         movups  $inout0,($out)
397         movups  $inout1,0x10($out)
398         movups  $inout2,0x20($out)
399         movups  $inout3,0x30($out)
400         jmp     .Lecb_ret
401 .align  16
402 .Lecb_dec_one:
403 ___
404         &aesni_generate1("dec",$key,$rounds);
405 $code.=<<___;
406         movups  $inout0,($out)
407         jmp     .Lecb_ret
408 .align  16
409 .Lecb_dec_two:
410         pxor    $inout2,$inout2
411         call    _aesni_decrypt3
412         movups  $inout0,($out)
413         movups  $inout1,0x10($out)
414         jmp     .Lecb_ret
415 .align  16
416 .Lecb_dec_three:
417         call    _aesni_decrypt3
418         movups  $inout0,($out)
419         movups  $inout1,0x10($out)
420         movups  $inout2,0x20($out)
421
422 .Lecb_ret:
423         ret
424 .size   aesni_ecb_encrypt,.-aesni_ecb_encrypt
425 ___
426 \f
427 {
428 ######################################################################
429 # void aesni_ccm64_[en|de]crypt_blocks (const void *in, void *out,
430 #                         size_t blocks, const AES_KEY *key,
431 #                         const char *ivec,char *cmac);
432 #
433 # Handles only complete blocks, operates on 64-bit counter and
434 # does not update *ivec! Nor does it finalize CMAC value
435 # (see engine/eng_aesni.c for details)
436 #
437 {
438 my $cmac="%r9"; # 6th argument
439
440 my $increment="%xmm8";
441 my $bswap_mask="%xmm9";
442
443 $code.=<<___;
444 .globl  aesni_ccm64_encrypt_blocks
445 .type   aesni_ccm64_encrypt_blocks,\@function,6
446 .align  16
447 aesni_ccm64_encrypt_blocks:
448 ___
449 $code.=<<___ if ($win64);
450         lea     -0x58(%rsp),%rsp
451         movaps  %xmm6,(%rsp)
452         movaps  %xmm7,0x10(%rsp)
453         movaps  %xmm8,0x20(%rsp)
454         movaps  %xmm9,0x30(%rsp)
455 .Lccm64_enc_body:
456 ___
457 $code.=<<___;
458         movdqu  ($ivp),$iv
459         movdqu  ($cmac),$inout1
460         movdqa  .Lincrement64(%rip),$increment
461         movdqa  .Lbswap_mask(%rip),$bswap_mask
462         pshufb  $bswap_mask,$iv                 # keep iv in reverse order
463
464         mov     240($key),$rounds               # key->rounds
465         mov     $key,$key_
466         mov     $rounds,$rnds_
467         movdqa  $iv,$inout0
468
469 .Lccm64_enc_outer:
470         movdqu  ($inp),$in0                     # load inp
471         pshufb  $bswap_mask,$inout0
472         mov     $key_,$key
473         mov     $rnds_,$rounds
474         pxor    $in0,$inout1                    # cmac^=inp
475         pxor    $inout2,$inout2
476
477         call    _aesni_encrypt3
478
479         paddq   $increment,$iv
480         dec     $len
481         lea     16($inp),$inp
482         pxor    $inout0,$in0                    # inp ^= E(iv)
483         movdqa  $iv,$inout0
484         movdqu  $in0,($out)                     # save output
485         lea     16($out),$out
486         jnz     .Lccm64_enc_outer
487
488         movdqu  $inout1,($cmac)
489 ___
490 $code.=<<___ if ($win64);
491         movaps  (%rsp),%xmm6
492         movaps  0x10(%rsp),%xmm7
493         movaps  0x20(%rsp),%xmm8
494         movaps  0x30(%rsp),%xmm9
495         lea     0x58(%rsp),%rsp
496 .Lccm64_enc_ret:
497 ___
498 $code.=<<___;
499         ret
500 .size   aesni_ccm64_encrypt_blocks,.-aesni_ccm64_encrypt_blocks
501 ___
502 ######################################################################
503 $code.=<<___;
504 .globl  aesni_ccm64_decrypt_blocks
505 .type   aesni_ccm64_decrypt_blocks,\@function,6
506 .align  16
507 aesni_ccm64_decrypt_blocks:
508 ___
509 $code.=<<___ if ($win64);
510         lea     -0x58(%rsp),%rsp
511         movaps  %xmm6,(%rsp)
512         movaps  %xmm7,0x10(%rsp)
513         movaps  %xmm8,0x20(%rsp)
514         movaps  %xmm9,0x30(%rsp)
515 .Lccm64_dec_body:
516 ___
517 $code.=<<___;
518         movdqu  ($ivp),$iv
519         movdqu  ($cmac),$inout1
520         movdqa  .Lincrement64(%rip),$increment
521         movdqa  .Lbswap_mask(%rip),$bswap_mask
522
523         mov     240($key),$rounds               # key->rounds
524         movdqa  $iv,$inout0
525         pshufb  $bswap_mask,$iv                 # keep iv in reverse order
526         mov     $rounds,$rnds_
527         mov     $key,$key_
528 ___
529         &aesni_generate1("enc",$key,$rounds);
530 $code.=<<___;
531 .Lccm64_dec_outer:
532         movdqu  ($inp),$in0                     # load inp
533         paddq   $increment,$iv
534         dec     $len
535         lea     16($inp),$inp
536         pxor    $inout0,$in0
537         movdqa  $iv,$inout0
538         mov     $key_,$key
539         mov     $rnds_,$rounds
540         pshufb  $bswap_mask,$inout0
541         movdqu  $in0,($out)
542         lea     16($out),$out
543         pxor    $in0,$inout1                    # cmac^=out
544
545         jz      .Lccm64_dec_break
546
547         pxor    $inout2,$inout2
548         call    _aesni_encrypt3
549
550         jmp     .Lccm64_dec_outer
551
552 .align  16
553 .Lccm64_dec_break:
554 ___
555         &aesni_generate1("enc",$key,$rounds,$inout1);
556 $code.=<<___;
557         movdqu  $inout1,($cmac)
558 ___
559 $code.=<<___ if ($win64);
560         movaps  (%rsp),%xmm6
561         movaps  0x10(%rsp),%xmm7
562         movaps  0x20(%rsp),%xmm8
563         movaps  0x30(%rsp),%xmm9
564         lea     0x58(%rsp),%rsp
565 .Lccm64_dec_ret:
566 ___
567 $code.=<<___;
568         ret
569 .size   aesni_ccm64_decrypt_blocks,.-aesni_ccm64_decrypt_blocks
570 ___
571 }\f
572 ######################################################################
573 # void aesni_ctr32_encrypt_blocks (const void *in, void *out,
574 #                         size_t blocks, const AES_KEY *key,
575 #                         const char *ivec);
576 #
577 # Handles only complete blocks, operates on 32-bit counter and
578 # does not update *ivec! (see engine/eng_aesni.c for details)
579 #
580 my $increment="%xmm10";
581 my $bswap_mask="%xmm11";
582
583 $code.=<<___;
584 .globl  aesni_ctr32_encrypt_blocks
585 .type   aesni_ctr32_encrypt_blocks,\@function,5
586 .align  16
587 aesni_ctr32_encrypt_blocks:
588 ___
589 $code.=<<___ if ($win64);
590         lea     -0x68(%rsp),%rsp
591         movaps  %xmm6,(%rsp)
592         movaps  %xmm7,0x10(%rsp)
593         movaps  %xmm8,0x20(%rsp)
594         movaps  %xmm9,0x30(%rsp)
595         movaps  %xmm10,0x40(%rsp)
596         movaps  %xmm11,0x50(%rsp)
597
598 .Lctr32_body:
599 ___
600 $code.=<<___;
601         cmp     \$1,$len
602         je      .Lctr32_one_shortcut
603
604         movdqu  ($ivp),$inout3
605         movdqa  .Lincrement32(%rip),$increment
606         movdqa  .Lbswap_mask(%rip),$bswap_mask
607         xor     $rounds,$rounds
608         pextrd  \$3,$inout3,$rnds_              # pull 32-bit counter
609         pinsrd  \$3,$rounds,$inout3             # wipe 32-bit counter
610
611         mov     240($key),$rounds               # key->rounds
612         pxor    $iv,$iv                         # vector of 3 32-bit counters
613         bswap   $rnds_
614         pinsrd  \$0,$rnds_,$iv
615         inc     $rnds_
616         pinsrd  \$1,$rnds_,$iv
617         inc     $rnds_
618         pinsrd  \$2,$rnds_,$iv
619         pshufb  $bswap_mask,$iv
620
621         cmp     \$4,$len
622         jbe     .Lctr32_tail
623         mov     $rounds,$rnds_
624         mov     $key,$key_
625         sub     \$4,$len
626
627 .Lctr32_loop3:
628         pshufd  \$`3<<6`,$iv,$inout0            # place counter to upper dword
629         pshufd  \$`2<<6`,$iv,$inout1
630         por     $inout3,$inout0                 # merge counter-less ivec
631         pshufd  \$`1<<6`,$iv,$inout2
632         por     $inout3,$inout1
633         por     $inout3,$inout2
634
635         # inline _aesni_encrypt3 and interleave last round
636         # with own code...
637
638         $movkey ($key),$rndkey0
639         shr     \$1,$rounds
640         $movkey 16($key),$rndkey1
641         lea     32($key),$key
642         pxor    $rndkey0,$inout0
643         pxor    $rndkey0,$inout1
644         pxor    $rndkey0,$inout2
645         $movkey ($key),$rndkey0
646         jmp     .Lctr32_enc_loop3
647 .align  16
648 .Lctr32_enc_loop3:
649         aesenc          $rndkey1,$inout0
650         aesenc          $rndkey1,$inout1
651         dec             $rounds
652         aesenc          $rndkey1,$inout2
653         $movkey         16($key),$rndkey1
654         aesenc          $rndkey0,$inout0
655         aesenc          $rndkey0,$inout1
656         lea             32($key),$key
657         aesenc          $rndkey0,$inout2
658         $movkey         ($key),$rndkey0
659         jnz             .Lctr32_enc_loop3
660
661         aesenc          $rndkey1,$inout0
662         aesenc          $rndkey1,$inout1
663         aesenc          $rndkey1,$inout2
664
665         pshufb          $bswap_mask,$iv
666         movdqu          ($inp),$in0
667         aesenclast      $rndkey0,$inout0
668         movdqu          0x10($inp),$in1
669         paddd           $increment,$iv
670         aesenclast      $rndkey0,$inout1
671         movdqu          0x20($inp),$in2
672         pshufb          $bswap_mask,$iv
673         aesenclast      $rndkey0,$inout2
674         lea             0x30($inp),$inp
675
676         mov     $key_,$key
677         pxor    $inout0,$in0
678         sub     \$3,$len
679         mov     $rnds_,$rounds
680         pxor    $inout1,$in1
681         movdqu  $in0,($out)
682         pxor    $inout2,$in2
683         movdqu  $in1,0x10($out)
684         movdqu  $in2,0x20($out)
685         lea     0x30($out),$out
686         ja      .Lctr32_loop3
687
688         pextrd  \$1,$iv,$rnds_                  # might need last counter value
689         add     \$4,$len
690         bswap   $rnds_
691
692 .Lctr32_tail:
693         pshufd  \$`3<<6`,$iv,$inout0
694         pshufd  \$`2<<6`,$iv,$inout1
695         por     $inout3,$inout0
696         movdqu  ($inp),$in0
697         cmp     \$2,$len
698         jb      .Lctr32_one
699         lea     1($rnds_),$rnds_
700         pshufd  \$`1<<6`,$iv,$inout2
701         por     $inout3,$inout1
702         movdqu  0x10($inp),$in1
703         je      .Lctr32_two
704         bswap   $rnds_
705         por     $inout3,$inout2
706         movdqu  0x20($inp),$in2
707         cmp     \$3,$len
708         je      .Lctr32_three
709
710         pinsrd  \$3,$rnds_,$inout3              # compose last counter value
711         movdqu  0x30($inp),$iv
712
713         call    _aesni_encrypt4
714
715         pxor    $inout0,$in0
716         pxor    $inout1,$in1
717         pxor    $inout2,$in2
718         movdqu  $in0,($out)
719         pxor    $inout3,$iv
720         movdqu  $in1,0x10($out)
721         movdqu  $in2,0x20($out)
722         movdqu  $iv,0x30($out)
723         jmp     .Lctr32_done
724
725 .align  16
726 .Lctr32_one_shortcut:
727         movdqu  ($ivp),$inout0
728         movdqu  ($inp),$in0
729         mov     240($key),$rounds               # key->rounds
730 .Lctr32_one:
731 ___
732         &aesni_generate1("enc",$key,$rounds);
733 $code.=<<___;
734         pxor    $inout0,$in0
735         movdqu  $in0,($out)
736         jmp     .Lctr32_done
737
738 .align  16
739 .Lctr32_two:
740         pxor    $inout2,$inout2
741         call    _aesni_encrypt3
742         pxor    $inout0,$in0
743         pxor    $inout1,$in1
744         movdqu  $in0,($out)
745         movdqu  $in1,0x10($out)
746         jmp     .Lctr32_done
747
748 .align  16
749 .Lctr32_three:
750         call    _aesni_encrypt3
751         pxor    $inout0,$in0
752         pxor    $inout1,$in1
753         pxor    $inout2,$in2
754         movdqu  $in0,($out)
755         movdqu  $in1,0x10($out)
756         movdqu  $in2,0x20($out)
757
758 .Lctr32_done:
759 ___
760
761 $code.=<<___ if ($win64);
762         movaps  (%rsp),%xmm6
763         movaps  0x10(%rsp),%xmm7
764         movaps  0x20(%rsp),%xmm8
765         movaps  0x30(%rsp),%xmm9
766         movaps  0x40(%rsp),%xmm10
767         movaps  0x50(%rsp),%xmm11
768         lea     0x68(%rsp),%rsp
769 .Lctr32_ret:
770 ___
771 $code.=<<___;
772         ret
773 .size   aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks
774 ___
775 }}
776 \f
777 ########################################################################
778 # void $PREFIX_cbc_encrypt (const void *inp, void *out,
779 #                           size_t length, const AES_KEY *key,
780 #                           unsigned char *ivp,const int enc);
781 $reserved = $win64?0x40:-0x18;  # used in decrypt
782 $code.=<<___;
783 .globl  ${PREFIX}_cbc_encrypt
784 .type   ${PREFIX}_cbc_encrypt,\@function,6
785 .align  16
786 ${PREFIX}_cbc_encrypt:
787         test    $len,$len               # check length
788         jz      .Lcbc_ret
789
790         mov     240($key),$rnds_        # pull $rounds
791         mov     $key,$key_              # backup $key
792         test    %r9d,%r9d               # 6th argument
793         jz      .Lcbc_decrypt
794 #--------------------------- CBC ENCRYPT ------------------------------#
795         movdqu  ($ivp),$inout0          # load iv as initial state
796         mov     $rnds_,$rounds
797         cmp     \$16,$len
798         jb      .Lcbc_enc_tail
799         sub     \$16,$len
800         jmp     .Lcbc_enc_loop
801 .align  16
802 .Lcbc_enc_loop:
803         movdqu  ($inp),$inout1          # load input
804         lea     16($inp),$inp
805         pxor    $inout1,$inout0
806 ___
807         &aesni_generate1("enc",$key,$rounds);
808 $code.=<<___;
809         mov     $rnds_,$rounds          # restore $rounds
810         mov     $key_,$key              # restore $key
811         movups  $inout0,0($out)         # store output
812         lea     16($out),$out
813         sub     \$16,$len
814         jnc     .Lcbc_enc_loop
815         add     \$16,$len
816         jnz     .Lcbc_enc_tail
817         movups  $inout0,($ivp)
818         jmp     .Lcbc_ret
819
820 .Lcbc_enc_tail:
821         mov     $len,%rcx       # zaps $key
822         xchg    $inp,$out       # $inp is %rsi and $out is %rdi now
823         .long   0x9066A4F3      # rep movsb
824         mov     \$16,%ecx       # zero tail
825         sub     $len,%rcx
826         xor     %eax,%eax
827         .long   0x9066AAF3      # rep stosb
828         lea     -16(%rdi),%rdi  # rewind $out by 1 block
829         mov     $rnds_,$rounds  # restore $rounds
830         mov     %rdi,%rsi       # $inp and $out are the same
831         mov     $key_,$key      # restore $key
832         xor     $len,$len       # len=16
833         jmp     .Lcbc_enc_loop  # one more spin
834 \f#--------------------------- CBC DECRYPT ------------------------------#
835 .align  16
836 .Lcbc_decrypt:
837 ___
838 $code.=<<___ if ($win64);
839         lea     -0x58(%rsp),%rsp
840         movaps  %xmm6,(%rsp)
841         movaps  %xmm7,0x10(%rsp)
842         movaps  %xmm8,0x20(%rsp)
843         movaps  %xmm9,0x30(%rsp)
844 .Lcbc_decrypt_body:
845 ___
846 $code.=<<___;
847         movups  ($ivp),$iv
848         mov     $rnds_,$rounds
849         cmp     \$0x40,$len
850         jbe     .Lcbc_dec_tail
851         sub     \$0x40,$len
852         jmp     .Lcbc_dec_loop3
853 .align  16
854 .Lcbc_dec_loop3:
855         movups  ($inp),$inout0
856         movups  0x10($inp),$inout1
857         movups  0x20($inp),$inout2
858         movaps  $inout0,$in0
859         movaps  $inout1,$in1
860         movaps  $inout2,$in2
861
862         call    _aesni_decrypt3
863
864         sub     \$0x30,$len
865         lea     0x30($inp),$inp
866         lea     0x30($out),$out
867         pxor    $iv,$inout0
868         pxor    $in0,$inout1
869         movaps  $in2,$iv
870         pxor    $in1,$inout2
871         movdqu  $inout0,-0x30($out)
872         mov     $rnds_,$rounds  # restore $rounds
873         movdqu  $inout1,-0x20($out)
874         mov     $key_,$key      # restore $key
875         movdqu  $inout2,-0x10($out)
876         ja      .Lcbc_dec_loop3
877
878         add     \$0x40,$len
879         movups  $iv,($ivp)
880 .Lcbc_dec_tail:
881         movups  ($inp),$inout0
882         movaps  $inout0,$in0
883         cmp     \$0x10,$len
884         jbe     .Lcbc_dec_one
885         movups  0x10($inp),$inout1
886         movaps  $inout1,$in1
887         cmp     \$0x20,$len
888         jbe     .Lcbc_dec_two
889         movups  0x20($inp),$inout2
890         movaps  $inout2,$in2
891         cmp     \$0x30,$len
892         jbe     .Lcbc_dec_three
893         movups  0x30($inp),$inout3
894         call    _aesni_decrypt4
895         pxor    $iv,$inout0
896         movups  0x30($inp),$iv
897         pxor    $in0,$inout1
898         movdqu  $inout0,($out)
899         pxor    $in1,$inout2
900         movdqu  $inout1,0x10($out)
901         pxor    $in2,$inout3
902         movdqu  $inout2,0x20($out)
903         movdqa  $inout3,$inout0
904         lea     0x30($out),$out
905         jmp     .Lcbc_dec_tail_collected
906 .align  16
907 .Lcbc_dec_one:
908 ___
909         &aesni_generate1("dec",$key,$rounds);
910 $code.=<<___;
911         pxor    $iv,$inout0
912         movaps  $in0,$iv
913         jmp     .Lcbc_dec_tail_collected
914 .align  16
915 .Lcbc_dec_two:
916         pxor    $inout2,$inout2
917         call    _aesni_decrypt3
918         pxor    $iv,$inout0
919         pxor    $in0,$inout1
920         movdqu  $inout0,($out)
921         movaps  $in1,$iv
922         movdqa  $inout1,$inout0
923         lea     0x10($out),$out
924         jmp     .Lcbc_dec_tail_collected
925 .align  16
926 .Lcbc_dec_three:
927         call    _aesni_decrypt3
928         pxor    $iv,$inout0
929         pxor    $in0,$inout1
930         movdqu  $inout0,($out)
931         pxor    $in1,$inout2
932         movdqu  $inout1,0x10($out)
933         movaps  $in2,$iv
934         movdqa  $inout2,$inout0
935         lea     0x20($out),$out
936         jmp     .Lcbc_dec_tail_collected
937 .align  16
938 .Lcbc_dec_tail_collected:
939         and     \$15,$len
940         movups  $iv,($ivp)
941         jnz     .Lcbc_dec_tail_partial
942         movdqu  $inout0,($out)
943         jmp     .Lcbc_dec_ret
944 .align  16
945 .Lcbc_dec_tail_partial:
946         movaps  $inout0,$reserved(%rsp)
947         mov     $out,%rdi
948         mov     $len,%rcx
949         lea     $reserved(%rsp),%rsi
950         .long   0x9066A4F3      # rep movsb
951
952 .Lcbc_dec_ret:
953 ___
954 $code.=<<___ if ($win64);
955         movaps  (%rsp),%xmm6
956         movaps  0x10(%rsp),%xmm7
957         movaps  0x20(%rsp),%xmm8
958         movaps  0x30(%rsp),%xmm9
959         lea     0x58(%rsp),%rsp
960 ___
961 $code.=<<___;
962 .Lcbc_ret:
963         ret
964 .size   ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt
965 ___
966 \f
967 # int $PREFIX_set_[en|de]crypt_key (const unsigned char *userKey,
968 #                               int bits, AES_KEY *key)
969 { my ($inp,$bits,$key) = @_4args;
970   $bits =~ s/%r/%e/;
971
972 $code.=<<___;
973 .globl  ${PREFIX}_set_decrypt_key
974 .type   ${PREFIX}_set_decrypt_key,\@abi-omnipotent
975 .align  16
976 ${PREFIX}_set_decrypt_key:
977         .byte   0x48,0x83,0xEC,0x08     # sub rsp,8
978         call    __aesni_set_encrypt_key
979         shl     \$4,$bits               # rounds-1 after _aesni_set_encrypt_key
980         test    %eax,%eax
981         jnz     .Ldec_key_ret
982         lea     16($key,$bits),$inp     # points at the end of key schedule
983
984         $movkey ($key),%xmm0            # just swap
985         $movkey ($inp),%xmm1
986         $movkey %xmm0,($inp)
987         $movkey %xmm1,($key)
988         lea     16($key),$key
989         lea     -16($inp),$inp
990
991 .Ldec_key_inverse:
992         $movkey ($key),%xmm0            # swap and inverse
993         $movkey ($inp),%xmm1
994         aesimc  %xmm0,%xmm0
995         aesimc  %xmm1,%xmm1
996         lea     16($key),$key
997         lea     -16($inp),$inp
998         $movkey %xmm0,16($inp)
999         $movkey %xmm1,-16($key)
1000         cmp     $key,$inp
1001         ja      .Ldec_key_inverse
1002
1003         $movkey ($key),%xmm0            # inverse middle
1004         aesimc  %xmm0,%xmm0
1005         $movkey %xmm0,($inp)
1006 .Ldec_key_ret:
1007         add     \$8,%rsp
1008         ret
1009 .LSEH_end_set_decrypt_key:
1010 .size   ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key
1011 ___
1012 \f
1013 # This is based on submission by
1014 #
1015 #       Huang Ying <ying.huang@intel.com>
1016 #       Vinodh Gopal <vinodh.gopal@intel.com>
1017 #       Kahraman Akdemir
1018 #
1019 # Agressively optimized in respect to aeskeygenassist's critical path
1020 # and is contained in %xmm0-5 to meet Win64 ABI requirement.
1021 #
1022 $code.=<<___;
1023 .globl  ${PREFIX}_set_encrypt_key
1024 .type   ${PREFIX}_set_encrypt_key,\@abi-omnipotent
1025 .align  16
1026 ${PREFIX}_set_encrypt_key:
1027 __aesni_set_encrypt_key:
1028         .byte   0x48,0x83,0xEC,0x08     # sub rsp,8
1029         mov     \$-1,%rax
1030         test    $inp,$inp
1031         jz      .Lenc_key_ret
1032         test    $key,$key
1033         jz      .Lenc_key_ret
1034
1035         movups  ($inp),%xmm0            # pull first 128 bits of *userKey
1036         pxor    %xmm4,%xmm4             # low dword of xmm4 is assumed 0
1037         lea     16($key),%rax
1038         cmp     \$256,$bits
1039         je      .L14rounds
1040         cmp     \$192,$bits
1041         je      .L12rounds
1042         cmp     \$128,$bits
1043         jne     .Lbad_keybits
1044
1045 .L10rounds:
1046         mov     \$9,$bits                       # 10 rounds for 128-bit key
1047         $movkey %xmm0,($key)                    # round 0
1048         aeskeygenassist \$0x1,%xmm0,%xmm1       # round 1
1049         call            .Lkey_expansion_128_cold
1050         aeskeygenassist \$0x2,%xmm0,%xmm1       # round 2
1051         call            .Lkey_expansion_128
1052         aeskeygenassist \$0x4,%xmm0,%xmm1       # round 3
1053         call            .Lkey_expansion_128
1054         aeskeygenassist \$0x8,%xmm0,%xmm1       # round 4
1055         call            .Lkey_expansion_128
1056         aeskeygenassist \$0x10,%xmm0,%xmm1      # round 5
1057         call            .Lkey_expansion_128
1058         aeskeygenassist \$0x20,%xmm0,%xmm1      # round 6
1059         call            .Lkey_expansion_128
1060         aeskeygenassist \$0x40,%xmm0,%xmm1      # round 7
1061         call            .Lkey_expansion_128
1062         aeskeygenassist \$0x80,%xmm0,%xmm1      # round 8
1063         call            .Lkey_expansion_128
1064         aeskeygenassist \$0x1b,%xmm0,%xmm1      # round 9
1065         call            .Lkey_expansion_128
1066         aeskeygenassist \$0x36,%xmm0,%xmm1      # round 10
1067         call            .Lkey_expansion_128
1068         $movkey %xmm0,(%rax)
1069         mov     $bits,80(%rax)  # 240(%rdx)
1070         xor     %eax,%eax
1071         jmp     .Lenc_key_ret
1072
1073 .align  16
1074 .L12rounds:
1075         movq    16($inp),%xmm2                  # remaining 1/3 of *userKey
1076         mov     \$11,$bits                      # 12 rounds for 192
1077         $movkey %xmm0,($key)                    # round 0
1078         aeskeygenassist \$0x1,%xmm2,%xmm1       # round 1,2
1079         call            .Lkey_expansion_192a_cold
1080         aeskeygenassist \$0x2,%xmm2,%xmm1       # round 2,3
1081         call            .Lkey_expansion_192b
1082         aeskeygenassist \$0x4,%xmm2,%xmm1       # round 4,5
1083         call            .Lkey_expansion_192a
1084         aeskeygenassist \$0x8,%xmm2,%xmm1       # round 5,6
1085         call            .Lkey_expansion_192b
1086         aeskeygenassist \$0x10,%xmm2,%xmm1      # round 7,8
1087         call            .Lkey_expansion_192a
1088         aeskeygenassist \$0x20,%xmm2,%xmm1      # round 8,9
1089         call            .Lkey_expansion_192b
1090         aeskeygenassist \$0x40,%xmm2,%xmm1      # round 10,11
1091         call            .Lkey_expansion_192a
1092         aeskeygenassist \$0x80,%xmm2,%xmm1      # round 11,12
1093         call            .Lkey_expansion_192b
1094         $movkey %xmm0,(%rax)
1095         mov     $bits,48(%rax)  # 240(%rdx)
1096         xor     %rax, %rax
1097         jmp     .Lenc_key_ret
1098
1099 .align  16
1100 .L14rounds:
1101         movups  16($inp),%xmm2                  # remaning half of *userKey
1102         mov     \$13,$bits                      # 14 rounds for 256
1103         lea     16(%rax),%rax
1104         $movkey %xmm0,($key)                    # round 0
1105         $movkey %xmm2,16($key)                  # round 1
1106         aeskeygenassist \$0x1,%xmm2,%xmm1       # round 2
1107         call            .Lkey_expansion_256a_cold
1108         aeskeygenassist \$0x1,%xmm0,%xmm1       # round 3
1109         call            .Lkey_expansion_256b
1110         aeskeygenassist \$0x2,%xmm2,%xmm1       # round 4
1111         call            .Lkey_expansion_256a
1112         aeskeygenassist \$0x2,%xmm0,%xmm1       # round 5
1113         call            .Lkey_expansion_256b
1114         aeskeygenassist \$0x4,%xmm2,%xmm1       # round 6
1115         call            .Lkey_expansion_256a
1116         aeskeygenassist \$0x4,%xmm0,%xmm1       # round 7
1117         call            .Lkey_expansion_256b
1118         aeskeygenassist \$0x8,%xmm2,%xmm1       # round 8
1119         call            .Lkey_expansion_256a
1120         aeskeygenassist \$0x8,%xmm0,%xmm1       # round 9
1121         call            .Lkey_expansion_256b
1122         aeskeygenassist \$0x10,%xmm2,%xmm1      # round 10
1123         call            .Lkey_expansion_256a
1124         aeskeygenassist \$0x10,%xmm0,%xmm1      # round 11
1125         call            .Lkey_expansion_256b
1126         aeskeygenassist \$0x20,%xmm2,%xmm1      # round 12
1127         call            .Lkey_expansion_256a
1128         aeskeygenassist \$0x20,%xmm0,%xmm1      # round 13
1129         call            .Lkey_expansion_256b
1130         aeskeygenassist \$0x40,%xmm2,%xmm1      # round 14
1131         call            .Lkey_expansion_256a
1132         $movkey %xmm0,(%rax)
1133         mov     $bits,16(%rax)  # 240(%rdx)
1134         xor     %rax,%rax
1135         jmp     .Lenc_key_ret
1136
1137 .align  16
1138 .Lbad_keybits:
1139         mov     \$-2,%rax
1140 .Lenc_key_ret:
1141         add     \$8,%rsp
1142         ret
1143 .LSEH_end_set_encrypt_key:
1144 \f
1145 .align  16
1146 .Lkey_expansion_128:
1147         $movkey %xmm0,(%rax)
1148         lea     16(%rax),%rax
1149 .Lkey_expansion_128_cold:
1150         shufps  \$0b00010000,%xmm0,%xmm4
1151         pxor    %xmm4, %xmm0
1152         shufps  \$0b10001100,%xmm0,%xmm4
1153         pxor    %xmm4, %xmm0
1154         pshufd  \$0b11111111,%xmm1,%xmm1        # critical path
1155         pxor    %xmm1,%xmm0
1156         ret
1157
1158 .align 16
1159 .Lkey_expansion_192a:
1160         $movkey %xmm0,(%rax)
1161         lea     16(%rax),%rax
1162 .Lkey_expansion_192a_cold:
1163         movaps  %xmm2, %xmm5
1164 .Lkey_expansion_192b_warm:
1165         shufps  \$0b00010000,%xmm0,%xmm4
1166         movaps  %xmm2,%xmm3
1167         pxor    %xmm4,%xmm0
1168         shufps  \$0b10001100,%xmm0,%xmm4
1169         pslldq  \$4,%xmm3
1170         pxor    %xmm4,%xmm0
1171         pshufd  \$0b01010101,%xmm1,%xmm1        # critical path
1172         pxor    %xmm3,%xmm2
1173         pxor    %xmm1,%xmm0
1174         pshufd  \$0b11111111,%xmm0,%xmm3
1175         pxor    %xmm3,%xmm2
1176         ret
1177
1178 .align 16
1179 .Lkey_expansion_192b:
1180         movaps  %xmm0,%xmm3
1181         shufps  \$0b01000100,%xmm0,%xmm5
1182         $movkey %xmm5,(%rax)
1183         shufps  \$0b01001110,%xmm2,%xmm3
1184         $movkey %xmm3,16(%rax)
1185         lea     32(%rax),%rax
1186         jmp     .Lkey_expansion_192b_warm
1187
1188 .align  16
1189 .Lkey_expansion_256a:
1190         $movkey %xmm2,(%rax)
1191         lea     16(%rax),%rax
1192 .Lkey_expansion_256a_cold:
1193         shufps  \$0b00010000,%xmm0,%xmm4
1194         pxor    %xmm4,%xmm0
1195         shufps  \$0b10001100,%xmm0,%xmm4
1196         pxor    %xmm4,%xmm0
1197         pshufd  \$0b11111111,%xmm1,%xmm1        # critical path
1198         pxor    %xmm1,%xmm0
1199         ret
1200
1201 .align 16
1202 .Lkey_expansion_256b:
1203         $movkey %xmm0,(%rax)
1204         lea     16(%rax),%rax
1205
1206         shufps  \$0b00010000,%xmm2,%xmm4
1207         pxor    %xmm4,%xmm2
1208         shufps  \$0b10001100,%xmm2,%xmm4
1209         pxor    %xmm4,%xmm2
1210         pshufd  \$0b10101010,%xmm1,%xmm1        # critical path
1211         pxor    %xmm1,%xmm2
1212         ret
1213 .size   ${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key
1214 ___
1215 }
1216 \f
1217 $code.=<<___;
1218 .align  64
1219 .Lbswap_mask:
1220         .byte   15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
1221 .Lincrement32:
1222         .long   3,3,3,0
1223 .Lincrement64:
1224         .long   1,0,0,0
1225 .asciz  "AES for Intel AES-NI, CRYPTOGAMS by <appro\@openssl.org>"
1226 .align  64
1227 ___
1228
1229 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
1230 #               CONTEXT *context,DISPATCHER_CONTEXT *disp)
1231 if ($win64) {
1232 $rec="%rcx";
1233 $frame="%rdx";
1234 $context="%r8";
1235 $disp="%r9";
1236
1237 $code.=<<___;
1238 .extern __imp_RtlVirtualUnwind
1239 ___
1240 $code.=<<___ if ($PREFIX eq "aesni");
1241 .type   ecb_se_handler,\@abi-omnipotent
1242 .align  16
1243 ecb_se_handler:
1244         push    %rsi
1245         push    %rdi
1246         push    %rbx
1247         push    %rbp
1248         push    %r12
1249         push    %r13
1250         push    %r14
1251         push    %r15
1252         pushfq
1253         sub     \$64,%rsp
1254
1255         mov     152($context),%rax      # pull context->Rsp
1256         mov     8(%rax),%rdi
1257         mov     16(%rax),%rsi
1258         mov     %rsi,168($context)      # restore context->Rsi
1259         mov     %rdi,176($context)      # restore context->Rdi
1260
1261         jmp     .Lcommon_seh_exit
1262 .size   ecb_se_handler,.-ecb_se_handler
1263
1264 .type   ccm64_se_handler,\@abi-omnipotent
1265 .align  16
1266 ccm64_se_handler:
1267         push    %rsi
1268         push    %rdi
1269         push    %rbx
1270         push    %rbp
1271         push    %r12
1272         push    %r13
1273         push    %r14
1274         push    %r15
1275         pushfq
1276         sub     \$64,%rsp
1277
1278         mov     120($context),%rax      # pull context->Rax
1279         mov     248($context),%rbx      # pull context->Rip
1280
1281         mov     8($disp),%rsi           # disp->ImageBase
1282         mov     56($disp),%r11          # disp->HandlerData
1283
1284         mov     0(%r11),%r10d           # HandlerData[0]
1285         lea     (%rsi,%r10),%r10        # prologue label
1286         cmp     %r10,%rbx               # context->Rip<prologue label
1287         jb      .Lin_ccm64_prologue
1288
1289         mov     152($context),%rax      # pull context->Rsp
1290
1291         mov     4(%r11),%r10d           # HandlerData[1]
1292         lea     (%rsi,%r10),%r10        # epilogue label
1293         cmp     %r10,%rbx               # context->Rip>=epilogue label
1294         jae     .Lin_ccm64_prologue
1295
1296         lea     0(%rax),%rsi            # top of stack
1297         lea     512($context),%rdi      # &context.Xmm6
1298         mov     \$8,%ecx                # 4*sizeof(%xmm0)/sizeof(%rax)
1299         .long   0xa548f3fc              # cld; rep movsq
1300         lea     0x58(%rax),%rax         # adjust stack pointer
1301
1302 .Lin_ccm64_prologue:
1303         mov     8(%rax),%rdi
1304         mov     16(%rax),%rsi
1305         mov     %rax,152($context)      # restore context->Rsp
1306         mov     %rsi,168($context)      # restore context->Rsi
1307         mov     %rdi,176($context)      # restore context->Rdi
1308
1309         jmp     .Lcommon_seh_exit
1310 .size   ccm64_se_handler,.-ccm64_se_handler
1311
1312 .type   ctr32_se_handler,\@abi-omnipotent
1313 .align  16
1314 ctr32_se_handler:
1315         push    %rsi
1316         push    %rdi
1317         push    %rbx
1318         push    %rbp
1319         push    %r12
1320         push    %r13
1321         push    %r14
1322         push    %r15
1323         pushfq
1324         sub     \$64,%rsp
1325
1326         mov     120($context),%rax      # pull context->Rax
1327         mov     248($context),%rbx      # pull context->Rip
1328
1329         lea     .Lctr32_body(%rip),%r10
1330         cmp     %r10,%rbx               # context->Rip<"prologue" label
1331         jb      .Lin_ctr32_prologue
1332
1333         mov     152($context),%rax      # pull context->Rsp
1334
1335         lea     .Lctr32_ret(%rip),%r10
1336         cmp     %r10,%rbx
1337         jae     .Lin_ctr32_prologue
1338
1339         lea     0(%rax),%rsi            # top of stack
1340         lea     512($context),%rdi      # &context.Xmm6
1341         mov     \$12,%ecx               # 6*sizeof(%xmm0)/sizeof(%rax)
1342         .long   0xa548f3fc              # cld; rep movsq
1343         lea     0x68(%rax),%rax         # adjust stack pointer
1344
1345 .Lin_ctr32_prologue:
1346         mov     8(%rax),%rdi
1347         mov     16(%rax),%rsi
1348         mov     %rax,152($context)      # restore context->Rsp
1349         mov     %rsi,168($context)      # restore context->Rsi
1350         mov     %rdi,176($context)      # restore context->Rdi
1351
1352         jmp     .Lcommon_seh_exit
1353 .size   ctr32_se_handler,.-ctr32_se_handler
1354 ___
1355 $code.=<<___;
1356 .type   cbc_se_handler,\@abi-omnipotent
1357 .align  16
1358 cbc_se_handler:
1359         push    %rsi
1360         push    %rdi
1361         push    %rbx
1362         push    %rbp
1363         push    %r12
1364         push    %r13
1365         push    %r14
1366         push    %r15
1367         pushfq
1368         sub     \$64,%rsp
1369
1370         mov     152($context),%rax      # pull context->Rsp
1371         mov     248($context),%rbx      # pull context->Rip
1372
1373         lea     .Lcbc_decrypt(%rip),%r10
1374         cmp     %r10,%rbx               # context->Rip<"prologue" label
1375         jb      .Lin_cbc_prologue
1376
1377         lea     .Lcbc_decrypt_body(%rip),%r10
1378         cmp     %r10,%rbx               # context->Rip<cbc_decrypt_body
1379         jb      .Lrestore_cbc_rax
1380
1381         lea     .Lcbc_ret(%rip),%r10
1382         cmp     %r10,%rbx               # context->Rip>="epilogue" label
1383         jae     .Lin_cbc_prologue
1384
1385         lea     0(%rax),%rsi            # top of stack
1386         lea     512($context),%rdi      # &context.Xmm6
1387         mov     \$8,%ecx                # 4*sizeof(%xmm0)/sizeof(%rax)
1388         .long   0xa548f3fc              # cld; rep movsq
1389         lea     0x58(%rax),%rax         # adjust stack pointer
1390         jmp     .Lin_cbc_prologue
1391
1392 .Lrestore_cbc_rax:
1393         mov     120($context),%rax
1394 .Lin_cbc_prologue:
1395         mov     8(%rax),%rdi
1396         mov     16(%rax),%rsi
1397         mov     %rax,152($context)      # restore context->Rsp
1398         mov     %rsi,168($context)      # restore context->Rsi
1399         mov     %rdi,176($context)      # restore context->Rdi
1400
1401 .Lcommon_seh_exit:
1402
1403         mov     40($disp),%rdi          # disp->ContextRecord
1404         mov     $context,%rsi           # context
1405         mov     \$154,%ecx              # sizeof(CONTEXT)
1406         .long   0xa548f3fc              # cld; rep movsq
1407
1408         mov     $disp,%rsi
1409         xor     %rcx,%rcx               # arg1, UNW_FLAG_NHANDLER
1410         mov     8(%rsi),%rdx            # arg2, disp->ImageBase
1411         mov     0(%rsi),%r8             # arg3, disp->ControlPc
1412         mov     16(%rsi),%r9            # arg4, disp->FunctionEntry
1413         mov     40(%rsi),%r10           # disp->ContextRecord
1414         lea     56(%rsi),%r11           # &disp->HandlerData
1415         lea     24(%rsi),%r12           # &disp->EstablisherFrame
1416         mov     %r10,32(%rsp)           # arg5
1417         mov     %r11,40(%rsp)           # arg6
1418         mov     %r12,48(%rsp)           # arg7
1419         mov     %rcx,56(%rsp)           # arg8, (NULL)
1420         call    *__imp_RtlVirtualUnwind(%rip)
1421
1422         mov     \$1,%eax                # ExceptionContinueSearch
1423         add     \$64,%rsp
1424         popfq
1425         pop     %r15
1426         pop     %r14
1427         pop     %r13
1428         pop     %r12
1429         pop     %rbp
1430         pop     %rbx
1431         pop     %rdi
1432         pop     %rsi
1433         ret
1434 .size   cbc_se_handler,.-cbc_se_handler
1435
1436 .section        .pdata
1437 .align  4
1438 ___
1439 $code.=<<___ if ($PREFIX eq "aesni");
1440         .rva    .LSEH_begin_aesni_ecb_encrypt
1441         .rva    .LSEH_end_aesni_ecb_encrypt
1442         .rva    .LSEH_info_ecb
1443
1444         .rva    .LSEH_begin_aesni_ccm64_encrypt_blocks
1445         .rva    .LSEH_end_aesni_ccm64_encrypt_blocks
1446         .rva    .LSEH_info_ccm64_enc
1447
1448         .rva    .LSEH_begin_aesni_ccm64_decrypt_blocks
1449         .rva    .LSEH_end_aesni_ccm64_decrypt_blocks
1450         .rva    .LSEH_info_ccm64_dec
1451
1452         .rva    .LSEH_begin_aesni_ctr32_encrypt_blocks
1453         .rva    .LSEH_end_aesni_ctr32_encrypt_blocks
1454         .rva    .LSEH_info_ctr32
1455 ___
1456 $code.=<<___;
1457         .rva    .LSEH_begin_${PREFIX}_cbc_encrypt
1458         .rva    .LSEH_end_${PREFIX}_cbc_encrypt
1459         .rva    .LSEH_info_cbc
1460
1461         .rva    ${PREFIX}_set_decrypt_key
1462         .rva    .LSEH_end_set_decrypt_key
1463         .rva    .LSEH_info_key
1464
1465         .rva    ${PREFIX}_set_encrypt_key
1466         .rva    .LSEH_end_set_encrypt_key
1467         .rva    .LSEH_info_key
1468 .section        .xdata
1469 .align  8
1470 ___
1471 $code.=<<___ if ($PREFIX eq "aesni");
1472 .LSEH_info_ecb:
1473         .byte   9,0,0,0
1474         .rva    ecb_se_handler
1475 .LSEH_info_ccm64_enc:
1476         .byte   9,0,0,0
1477         .rva    ccm64_se_handler
1478         .rva    .Lccm64_enc_body,.Lccm64_enc_ret        # HandlerData[]
1479 .LSEH_info_ccm64_dec:
1480         .byte   9,0,0,0
1481         .rva    ccm64_se_handler
1482         .rva    .Lccm64_dec_body,.Lccm64_dec_ret        # HandlerData[]
1483 .LSEH_info_ctr32:
1484         .byte   9,0,0,0
1485         .rva    ctr32_se_handler
1486 ___
1487 $code.=<<___;
1488 .LSEH_info_cbc:
1489         .byte   9,0,0,0
1490         .rva    cbc_se_handler
1491 .LSEH_info_key:
1492         .byte   0x01,0x04,0x01,0x00
1493         .byte   0x04,0x02,0x00,0x00     # sub rsp,8
1494 ___
1495 }
1496
1497 sub rex {
1498  local *opcode=shift;
1499  my ($dst,$src)=@_;
1500
1501    if ($dst>=8 || $src>=8) {
1502         $rex=0x40;
1503         $rex|=0x04 if($dst>=8);
1504         $rex|=0x01 if($src>=8);
1505         push @opcode,$rex;
1506    }
1507 }
1508
1509 sub aesni {
1510   my $line=shift;
1511   my @opcode=(0x66);
1512
1513     if ($line=~/(aeskeygenassist)\s+\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
1514         rex(\@opcode,$4,$3);
1515         push @opcode,0x0f,0x3a,0xdf;
1516         push @opcode,0xc0|($3&7)|(($4&7)<<3);   # ModR/M
1517         my $c=$2;
1518         push @opcode,$c=~/^0/?oct($c):$c;
1519         return ".byte\t".join(',',@opcode);
1520     }
1521     elsif ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) {
1522         my %opcodelet = (
1523                 "aesimc" => 0xdb,
1524                 "aesenc" => 0xdc,       "aesenclast" => 0xdd,
1525                 "aesdec" => 0xde,       "aesdeclast" => 0xdf
1526         );
1527         return undef if (!defined($opcodelet{$1}));
1528         rex(\@opcode,$3,$2);
1529         push @opcode,0x0f,0x38,$opcodelet{$1};
1530         push @opcode,0xc0|($2&7)|(($3&7)<<3);   # ModR/M
1531         return ".byte\t".join(',',@opcode);
1532     }
1533     return $line;
1534 }
1535
1536 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
1537 $code =~ s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/gem;
1538
1539 print $code;
1540
1541 close STDOUT;