Rework framework for assembler support for AES counter mode and add
[oweals/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 $PREFIX="aesni";        # if $PREFIX is set to "AES", the script
16                         # generates drop-in replacement for
17                         # crypto/aes/asm/aes-x86_64.pl:-)
18
19 $flavour = shift;
20 $output  = shift;
21 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
22
23 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
24
25 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
26 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
27 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
28 die "can't locate x86_64-xlate.pl";
29
30 open STDOUT,"| $^X $xlate $flavour $output";
31
32 $movkey = $PREFIX eq "aesni" ? "movaps" : "movups";
33 @_4args=$win64? ("%rcx","%rdx","%r8", "%r9") :  # Win64 order
34                 ("%rdi","%rsi","%rdx","%rcx");  # Unix order
35
36 $code=".text\n";
37
38 $rounds="%eax"; # input to and changed by aesni_[en|de]cryptN !!!
39 # this is natural Unix argument order for public $PREFIX_[ecb|cbc]_encrypt ...
40 $inp="%rdi";
41 $out="%rsi";
42 $len="%rdx";
43 $key="%rcx";    # input to and changed by aesni_[en|de]cryptN !!!
44 $ivp="%r8";     # cbc, ctr
45
46 $rnds_="%r10d"; # backup copy for $rounds
47 $key_="%r11";   # backup copy for $key
48
49 # %xmm register layout
50 $inout0="%xmm0";        $inout1="%xmm1";
51 $inout2="%xmm2";        $inout3="%xmm3";
52 $rndkey0="%xmm4";       $rndkey1="%xmm5";
53
54 $iv="%xmm6";            $in0="%xmm7";   # used in CBC decrypt, CTR
55 $in1="%xmm8";           $in2="%xmm9";
56 \f
57 # Inline version of internal aesni_[en|de]crypt1.
58 #
59 # Why folded loop? Because aes[enc|dec] is slow enough to accommodate
60 # cycles which take care of loop variables...
61 { my $sn;
62 sub aesni_generate1 {
63 my ($p,$key,$rounds)=@_;
64 ++$sn;
65 $code.=<<___;
66         $movkey ($key),$rndkey0
67         $movkey 16($key),$rndkey1
68         lea     32($key),$key
69         pxor    $rndkey0,$inout0
70 .Loop_${p}1_$sn:
71         aes${p} $rndkey1,$inout0
72         dec     $rounds
73         $movkey ($key),$rndkey1
74         lea     16($key),$key
75         jnz     .Loop_${p}1_$sn # loop body is 16 bytes
76         aes${p}last     $rndkey1,$inout0
77 ___
78 }}
79 # void $PREFIX_[en|de]crypt (const void *inp,void *out,const AES_KEY *key);
80 #
81 { my ($inp,$out,$key) = @_4args;
82
83 $code.=<<___;
84 .globl  ${PREFIX}_encrypt
85 .type   ${PREFIX}_encrypt,\@abi-omnipotent
86 .align  16
87 ${PREFIX}_encrypt:
88         movups  ($inp),$inout0          # load input
89         mov     240($key),$rounds       # pull $rounds
90 ___
91         &aesni_generate1("enc",$key,$rounds);
92 $code.=<<___;
93         movups  $inout0,($out)          # output
94         ret
95 .size   ${PREFIX}_encrypt,.-${PREFIX}_encrypt
96
97 .globl  ${PREFIX}_decrypt
98 .type   ${PREFIX}_decrypt,\@abi-omnipotent
99 .align  16
100 ${PREFIX}_decrypt:
101         movups  ($inp),$inout0          # load input
102         mov     240($key),$rounds       # pull $rounds
103 ___
104         &aesni_generate1("dec",$key,$rounds);
105 $code.=<<___;
106         movups  $inout0,($out)          # output
107         ret
108 .size   ${PREFIX}_decrypt, .-${PREFIX}_decrypt
109 ___
110 }
111 \f
112 # _aesni_[en|de]crypt[34] are private interfaces, N denotes interleave
113 # factor. Why 3x subroutine is used in loops? Even though aes[enc|dec]
114 # latency is 6, it turned out that it can be scheduled only every
115 # *second* cycle. Thus 3x interleave is the one providing optimal
116 # utilization, i.e. when subroutine's throughput is virtually same as
117 # of non-interleaved subroutine [for number of input blocks up to 3].
118 # This is why it makes no sense to implement 2x subroutine. As soon
119 # as/if Intel improves throughput by making it possible to schedule
120 # the instructions in question *every* cycles I would have to
121 # implement 6x interleave and use it in loop...
122 sub aesni_generate3 {
123 my $dir=shift;
124 # As already mentioned it takes in $key and $rounds, which are *not*
125 # preserved. $inout[0-2] is cipher/clear text...
126 $code.=<<___;
127 .type   _aesni_${dir}rypt3,\@abi-omnipotent
128 .align  16
129 _aesni_${dir}rypt3:
130         $movkey ($key),$rndkey0
131         shr     \$1,$rounds
132         $movkey 16($key),$rndkey1
133         lea     32($key),$key
134         pxor    $rndkey0,$inout0
135         pxor    $rndkey0,$inout1
136         pxor    $rndkey0,$inout2
137
138 .L${dir}_loop3:
139         aes${dir}       $rndkey1,$inout0
140         $movkey         ($key),$rndkey0
141         aes${dir}       $rndkey1,$inout1
142         dec             $rounds
143         aes${dir}       $rndkey1,$inout2
144         aes${dir}       $rndkey0,$inout0
145         $movkey         16($key),$rndkey1
146         aes${dir}       $rndkey0,$inout1
147         lea             32($key),$key
148         aes${dir}       $rndkey0,$inout2
149         jnz             .L${dir}_loop3
150
151         aes${dir}       $rndkey1,$inout0
152         $movkey         ($key),$rndkey0
153         aes${dir}       $rndkey1,$inout1
154         aes${dir}       $rndkey1,$inout2
155         aes${dir}last   $rndkey0,$inout0
156         aes${dir}last   $rndkey0,$inout1
157         aes${dir}last   $rndkey0,$inout2
158         ret
159 .size   _aesni_${dir}rypt3,.-_aesni_${dir}rypt3
160 ___
161 }
162 # 4x interleave is implemented to improve small block performance,
163 # most notably [and naturally] 4 block by ~30%. One can argue that one
164 # should have implemented 5x as well, but improvement would be <20%,
165 # so it's not worth it...
166 sub aesni_generate4 {
167 my $dir=shift;
168 # As already mentioned it takes in $key and $rounds, which are *not*
169 # preserved. $inout[0-3] is cipher/clear text...
170 $code.=<<___;
171 .type   _aesni_${dir}rypt4,\@abi-omnipotent
172 .align  16
173 _aesni_${dir}rypt4:
174         $movkey ($key),$rndkey0
175         shr     \$1,$rounds
176         $movkey 16($key),$rndkey1
177         lea     32($key),$key
178         pxor    $rndkey0,$inout0
179         pxor    $rndkey0,$inout1
180         pxor    $rndkey0,$inout2
181         pxor    $rndkey0,$inout3
182
183 .L${dir}_loop4:
184         aes${dir}       $rndkey1,$inout0
185         $movkey         ($key),$rndkey0
186         aes${dir}       $rndkey1,$inout1
187         dec             $rounds
188         aes${dir}       $rndkey1,$inout2
189         aes${dir}       $rndkey1,$inout3
190         aes${dir}       $rndkey0,$inout0
191         $movkey         16($key),$rndkey1
192         aes${dir}       $rndkey0,$inout1
193         lea             32($key),$key
194         aes${dir}       $rndkey0,$inout2
195         aes${dir}       $rndkey0,$inout3
196         jnz             .L${dir}_loop4
197
198         aes${dir}       $rndkey1,$inout0
199         $movkey         ($key),$rndkey0
200         aes${dir}       $rndkey1,$inout1
201         aes${dir}       $rndkey1,$inout2
202         aes${dir}       $rndkey1,$inout3
203         aes${dir}last   $rndkey0,$inout0
204         aes${dir}last   $rndkey0,$inout1
205         aes${dir}last   $rndkey0,$inout2
206         aes${dir}last   $rndkey0,$inout3
207         ret
208 .size   _aesni_${dir}rypt4,.-_aesni_${dir}rypt4
209 ___
210 }
211 &aesni_generate3("enc") if ($PREFIX eq "aesni");
212 &aesni_generate3("dec");
213 &aesni_generate4("enc") if ($PREFIX eq "aesni");
214 &aesni_generate4("dec");
215 \f
216 if ($PREFIX eq "aesni") {
217 ########################################################################
218 # void aesni_ecb_encrypt (const void *in, void *out,
219 #                         size_t length, const AES_KEY *key,
220 #                         int enc);
221 $code.=<<___;
222 .globl  aesni_ecb_encrypt
223 .type   aesni_ecb_encrypt,\@function,5
224 .align  16
225 aesni_ecb_encrypt:
226         cmp     \$16,$len               # check length
227         jb      .Lecb_ret
228
229         mov     240($key),$rounds       # pull $rounds
230         and     \$-16,$len
231         mov     $key,$key_              # backup $key
232         test    %r8d,%r8d               # 5th argument
233         mov     $rounds,$rnds_          # backup $rounds
234         jz      .Lecb_decrypt
235 #--------------------------- ECB ENCRYPT ------------------------------#
236         cmp     \$0x40,$len
237         jbe     .Lecb_enc_tail
238         sub     \$0x40,$len
239         jmp     .Lecb_enc_loop3
240 .align 16
241 .Lecb_enc_loop3:
242         movups  ($inp),$inout0
243         movups  0x10($inp),$inout1
244         movups  0x20($inp),$inout2
245         call    _aesni_encrypt3
246         sub     \$0x30,$len
247         lea     0x30($inp),$inp
248         lea     0x30($out),$out
249         movups  $inout0,-0x30($out)
250         mov     $rnds_,$rounds          # restore $rounds
251         movups  $inout1,-0x20($out)
252         mov     $key_,$key              # restore $key
253         movups  $inout2,-0x10($out)
254         ja      .Lecb_enc_loop3
255
256         add     \$0x40,$len
257         jz      .Lecb_ret
258
259 .Lecb_enc_tail:
260         cmp     \$0x20,$len
261         movups  ($inp),$inout0
262         jb      .Lecb_enc_one
263         movups  0x10($inp),$inout1
264         je      .Lecb_enc_two
265         cmp     \$0x30,$len
266         movups  0x20($inp),$inout2
267         je      .Lecb_enc_three
268         movups  0x30($inp),$inout3
269         call    _aesni_encrypt4
270         movups  $inout0,($out)
271         movups  $inout1,0x10($out)
272         movups  $inout2,0x20($out)
273         movups  $inout3,0x30($out)
274         jmp     .Lecb_ret
275 .align  16
276 .Lecb_enc_one:
277 ___
278         &aesni_generate1("enc",$key,$rounds);
279 $code.=<<___;
280         movups  $inout0,($out)
281         jmp     .Lecb_ret
282 .align  16
283 .Lecb_enc_two:
284         call    _aesni_encrypt3
285         movups  $inout0,($out)
286         movups  $inout1,0x10($out)
287         jmp     .Lecb_ret
288 .align  16
289 .Lecb_enc_three:
290         call    _aesni_encrypt3
291         movups  $inout0,($out)
292         movups  $inout1,0x10($out)
293         movups  $inout2,0x20($out)
294         jmp     .Lecb_ret
295 \f#--------------------------- ECB DECRYPT ------------------------------#
296 .align  16
297 .Lecb_decrypt:
298         cmp     \$0x40,$len
299         jbe     .Lecb_dec_tail
300         sub     \$0x40,$len
301         jmp     .Lecb_dec_loop3
302 .align 16
303 .Lecb_dec_loop3:
304         movups  ($inp),$inout0
305         movups  0x10($inp),$inout1
306         movups  0x20($inp),$inout2
307         call    _aesni_decrypt3
308         sub     \$0x30,$len
309         lea     0x30($inp),$inp
310         lea     0x30($out),$out
311         movups  $inout0,-0x30($out)
312         mov     $rnds_,$rounds          # restore $rounds
313         movups  $inout1,-0x20($out)
314         mov     $key_,$key              # restore $key
315         movups  $inout2,-0x10($out)
316         ja      .Lecb_dec_loop3
317
318         add     \$0x40,$len
319         jz      .Lecb_ret
320
321 .Lecb_dec_tail:
322         cmp     \$0x20,$len
323         movups  ($inp),$inout0
324         jb      .Lecb_dec_one
325         movups  0x10($inp),$inout1
326         je      .Lecb_dec_two
327         cmp     \$0x30,$len
328         movups  0x20($inp),$inout2
329         je      .Lecb_dec_three
330         movups  0x30($inp),$inout3
331         call    _aesni_decrypt4
332         movups  $inout0,($out)
333         movups  $inout1,0x10($out)
334         movups  $inout2,0x20($out)
335         movups  $inout3,0x30($out)
336         jmp     .Lecb_ret
337 .align  16
338 .Lecb_dec_one:
339 ___
340         &aesni_generate1("dec",$key,$rounds);
341 $code.=<<___;
342         movups  $inout0,($out)
343         jmp     .Lecb_ret
344 .align  16
345 .Lecb_dec_two:
346         call    _aesni_decrypt3
347         movups  $inout0,($out)
348         movups  $inout1,0x10($out)
349         jmp     .Lecb_ret
350 .align  16
351 .Lecb_dec_three:
352         call    _aesni_decrypt3
353         movups  $inout0,($out)
354         movups  $inout1,0x10($out)
355         movups  $inout2,0x20($out)
356
357 .Lecb_ret:
358         ret
359 .size   aesni_ecb_encrypt,.-aesni_ecb_encrypt
360 ___
361 ######################################################################
362 # handles only complete blocks, operates on 32-bit counter and
363 # does not update *ivec! (see engine/eng_aesni.c for details)
364 #
365 # void aesni_ctr32_encrypt_blocks (const void *in, void *out,
366 #                         size_t blocks, const AES_KEY *key,
367 #                         const char *ivec);
368 $increment="%xmm10";
369 $bswap_mask="%xmm11";
370
371 $code.=<<___;
372 .globl  aesni_ctr32_encrypt_blocks
373 .type   aesni_ctr32_encrypt_blocks,\@function,5
374 .align  16
375 aesni_ctr32_encrypt_blocks:
376 ___
377 $code.=<<___ if ($win64);
378         lea     -0x68(%rsp),%rsp
379         movaps  %xmm6,(%rsp)
380         movaps  %xmm7,0x10(%rsp)
381         movaps  %xmm8,0x20(%rsp)
382         movaps  %xmm9,0x30(%rsp)
383         movaps  %xmm10,0x40(%rsp)
384         movaps  %xmm11,0x50(%rsp)
385
386 .Lctr32_body:
387 ___
388 $code.=<<___;
389         movups  ($ivp),$inout3
390         movaps  .Lincrement(%rip),$increment
391         movaps  .Lbswap_mask(%rip),$bswap_mask
392         xor     $rounds,$rounds
393         pextrd  \$3,$inout3,$rnds_              # pull 32-bit counter
394         pinsrd  \$3,$rounds,$inout3             # wipe 32-bit counter
395
396         mov     240($key),$rounds               # key->rounds
397         pxor    $iv,$iv                         # vector of 3 32-bit counters
398         bswap   $rnds_
399         pinsrd  \$0,$rnds_,$iv
400         inc     $rnds_
401         pinsrd  \$1,$rnds_,$iv
402         inc     $rnds_
403         pinsrd  \$2,$rnds_,$iv
404
405         cmp     \$4,$len
406         pshufb  $bswap_mask,$iv
407         jbe     .Lctr32_tail
408         mov     $rounds,$rnds_
409         mov     $key,$key_
410         sub     \$4,$len
411         jmp     .Lctr32_loop3
412
413 .align  16
414 .Lctr32_loop3:
415         pshufd  \$`3<<6`,$iv,$inout0            # place counter to upper dword
416         pshufd  \$`2<<6`,$iv,$inout1
417         pshufd  \$`1<<6`,$iv,$inout2
418         movups  ($inp),$in0
419         movups  0x10($inp),$in1
420         movups  0x20($inp),$in2
421         por     $inout3,$inout0                 # merge counter-less ivec
422         por     $inout3,$inout1
423         por     $inout3,$inout2
424         pshufb  $bswap_mask,$iv
425
426         call    _aesni_encrypt3
427
428         paddd   $increment,$iv
429         pxor    $inout0,$in0
430         pxor    $inout1,$in1
431         pxor    $inout2,$in2
432         pshufb  $bswap_mask,$iv
433         movups  $in0,($out)
434         movups  $in1,0x10($out)
435         movups  $in2,0x20($out)
436
437         sub     \$3,$len
438         lea     0x30($inp),$inp
439         lea     0x30($out),$out
440         mov     $key_,$key
441         mov     $rnds_,$rounds
442         ja      .Lctr32_loop3
443
444         add     \$4,$len
445         pextrd  \$1,$iv,$rnds_                  # migh need last counter value
446         jz      .Lctr32_done
447         bswap   $rnds_
448
449 .Lctr32_tail:
450         cmp     \$2,$len
451         pshufd  \$`3<<6`,$iv,$inout0
452         pshufd  \$`2<<6`,$iv,$inout1
453         pshufd  \$`1<<6`,$iv,$inout2
454         por     $inout3,$inout0
455         movups  ($inp),$in0
456         jb      .Lctr32_one
457         por     $inout3,$inout1
458         movups  0x10($inp),$in1
459         je      .Lctr32_two
460         cmp     \$3,$len
461         por     $inout3,$inout2
462         movups  0x20($inp),$in2
463         je      .Lctr32_three
464
465         inc     $rnds_                          # compose last counter value
466         bswap   $rnds_
467         pinsrd  \$3,$rnds_,$inout3
468         movups  0x30($inp),$iv
469
470         call    _aesni_encrypt4
471
472         pxor    $inout0,$in0
473         pxor    $inout1,$in1
474         pxor    $inout2,$in2
475         pxor    $inout3,$iv
476         movups  $in0,($out)
477         movups  $in1,0x10($out)
478         movups  $in2,0x20($out)
479         movups  $iv,0x30($out)
480         jmp     .Lctr32_done
481
482 .align  16
483 .Lctr32_one:
484 ___
485         &aesni_generate1("enc",$key,$rounds);
486 $code.=<<___;
487         pxor    $inout0,$in0
488         movups  $in0,($out)
489         jmp     .Lctr32_done
490
491 .align  16
492 .Lctr32_two:
493         call    _aesni_encrypt3
494         pxor    $inout0,$in0
495         pxor    $inout1,$in1
496         movups  $in0,($out)
497         movups  $in1,0x10($out)
498         jmp     .Lctr32_done
499
500 .align  16
501 .Lctr32_three:
502         call    _aesni_encrypt3
503         pxor    $inout0,$in0
504         pxor    $inout1,$in1
505         pxor    $inout2,$in2
506         movups  $in0,($out)
507         movups  $in1,0x10($out)
508         movups  $in2,0x20($out)
509
510 .Lctr32_done:
511 ___
512
513 $code.=<<___ if ($win64);
514         movaps  (%rsp),%xmm6
515         movaps  0x10(%rsp),%xmm7
516         movaps  0x20(%rsp),%xmm8
517         movaps  0x30(%rsp),%xmm9
518         movaps  0x40(%rsp),%xmm10
519         movaps  0x50(%rsp),%xmm11
520         lea     0x68(%rsp),%rsp
521 ___
522 $code.=<<___;
523 .Lctr32_ret:
524         ret
525 .size   aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks
526 ___
527 }
528 \f
529 ########################################################################
530 # void $PREFIX_cbc_encrypt (const void *inp, void *out,
531 #                           size_t length, const AES_KEY *key,
532 #                           unsigned char *ivp,const int enc);
533 $reserved = $win64?0x40:-0x18;  # used in decrypt
534 $code.=<<___;
535 .globl  ${PREFIX}_cbc_encrypt
536 .type   ${PREFIX}_cbc_encrypt,\@function,6
537 .align  16
538 ${PREFIX}_cbc_encrypt:
539         test    $len,$len               # check length
540         jz      .Lcbc_ret
541
542         mov     240($key),$rnds_        # pull $rounds
543         mov     $key,$key_              # backup $key
544         test    %r9d,%r9d               # 6th argument
545         jz      .Lcbc_decrypt
546 #--------------------------- CBC ENCRYPT ------------------------------#
547         movups  ($ivp),$inout0          # load iv as initial state
548         cmp     \$16,$len
549         mov     $rnds_,$rounds
550         jb      .Lcbc_enc_tail
551         sub     \$16,$len
552         jmp     .Lcbc_enc_loop
553 .align 16
554 .Lcbc_enc_loop:
555         movups  ($inp),$inout1          # load input
556         lea     16($inp),$inp
557         pxor    $inout1,$inout0
558 ___
559         &aesni_generate1("enc",$key,$rounds);
560 $code.=<<___;
561         sub     \$16,$len
562         lea     16($out),$out
563         mov     $rnds_,$rounds          # restore $rounds
564         mov     $key_,$key              # restore $key
565         movups  $inout0,-16($out)       # store output
566         jnc     .Lcbc_enc_loop
567         add     \$16,$len
568         jnz     .Lcbc_enc_tail
569         movups  $inout0,($ivp)
570         jmp     .Lcbc_ret
571
572 .Lcbc_enc_tail:
573         mov     $len,%rcx       # zaps $key
574         xchg    $inp,$out       # $inp is %rsi and $out is %rdi now
575         .long   0x9066A4F3      # rep movsb
576         mov     \$16,%ecx       # zero tail
577         sub     $len,%rcx
578         xor     %eax,%eax
579         .long   0x9066AAF3      # rep stosb
580         lea     -16(%rdi),%rdi  # rewind $out by 1 block
581         mov     $rnds_,$rounds  # restore $rounds
582         mov     %rdi,%rsi       # $inp and $out are the same
583         mov     $key_,$key      # restore $key
584         xor     $len,$len       # len=16
585         jmp     .Lcbc_enc_loop  # one more spin
586 \f#--------------------------- CBC DECRYPT ------------------------------#
587 .align  16
588 .Lcbc_decrypt:
589 ___
590 $code.=<<___ if ($win64);
591         lea     -0x58(%rsp),%rsp
592         movaps  %xmm6,(%rsp)
593         movaps  %xmm7,0x10(%rsp)
594         movaps  %xmm8,0x20(%rsp)
595         movaps  %xmm9,0x30(%rsp)
596 .Lcbc_decrypt_body:
597 ___
598 $code.=<<___;
599         movups  ($ivp),$iv
600         cmp     \$0x40,$len
601         mov     $rnds_,$rounds
602         jbe     .Lcbc_dec_tail
603         sub     \$0x40,$len
604         jmp     .Lcbc_dec_loop3
605 .align 16
606 .Lcbc_dec_loop3:
607         movups  ($inp),$inout0
608         movups  0x10($inp),$inout1
609         movups  0x20($inp),$inout2
610         movaps  $inout0,$in0
611         movaps  $inout1,$in1
612         movaps  $inout2,$in2
613         call    _aesni_decrypt3
614         sub     \$0x30,$len
615         lea     0x30($inp),$inp
616         lea     0x30($out),$out
617         pxor    $iv,$inout0
618         pxor    $in0,$inout1
619         movaps  $in2,$iv
620         pxor    $in1,$inout2
621         movups  $inout0,-0x30($out)
622         mov     $rnds_,$rounds  # restore $rounds
623         movups  $inout1,-0x20($out)
624         mov     $key_,$key      # restore $key
625         movups  $inout2,-0x10($out)
626         ja      .Lcbc_dec_loop3
627
628         add     \$0x40,$len
629         movups  $iv,($ivp)
630         jz      .Lcbc_dec_ret
631
632 .Lcbc_dec_tail:
633         movups  ($inp),$inout0
634         cmp     \$0x10,$len
635         movaps  $inout0,$in0
636         jbe     .Lcbc_dec_one
637         movups  0x10($inp),$inout1
638         cmp     \$0x20,$len
639         movaps  $inout1,$in1
640         jbe     .Lcbc_dec_two
641         movups  0x20($inp),$inout2
642         cmp     \$0x30,$len
643         movaps  $inout2,$in2
644         jbe     .Lcbc_dec_three
645         movups  0x30($inp),$inout3
646         call    _aesni_decrypt4
647         pxor    $iv,$inout0
648         movups  0x30($inp),$iv
649         pxor    $in0,$inout1
650         movups  $inout0,($out)
651         pxor    $in1,$inout2
652         movups  $inout1,0x10($out)
653         pxor    $in2,$inout3
654         movups  $inout2,0x20($out)
655         movaps  $inout3,$inout0
656         lea     0x30($out),$out
657         jmp     .Lcbc_dec_tail_collected
658 .align  16
659 .Lcbc_dec_one:
660 ___
661         &aesni_generate1("dec",$key,$rounds);
662 $code.=<<___;
663         pxor    $iv,$inout0
664         movaps  $in0,$iv
665         jmp     .Lcbc_dec_tail_collected
666 .align  16
667 .Lcbc_dec_two:
668         call    _aesni_decrypt3
669         pxor    $iv,$inout0
670         pxor    $in0,$inout1
671         movups  $inout0,($out)
672         movaps  $in1,$iv
673         movaps  $inout1,$inout0
674         lea     0x10($out),$out
675         jmp     .Lcbc_dec_tail_collected
676 .align  16
677 .Lcbc_dec_three:
678         call    _aesni_decrypt3
679         pxor    $iv,$inout0
680         pxor    $in0,$inout1
681         movups  $inout0,($out)
682         pxor    $in1,$inout2
683         movups  $inout1,0x10($out)
684         movaps  $in2,$iv
685         movaps  $inout2,$inout0
686         lea     0x20($out),$out
687         jmp     .Lcbc_dec_tail_collected
688 .align  16
689 .Lcbc_dec_tail_collected:
690         and     \$15,$len
691         movups  $iv,($ivp)
692         jnz     .Lcbc_dec_tail_partial
693         movups  $inout0,($out)
694         jmp     .Lcbc_dec_ret
695 .Lcbc_dec_tail_partial:
696         movaps  $inout0,$reserved(%rsp)
697         mov     $out,%rdi
698         mov     $len,%rcx
699         lea     $reserved(%rsp),%rsi
700         .long   0x9066A4F3      # rep movsb
701
702 .Lcbc_dec_ret:
703 ___
704 $code.=<<___ if ($win64);
705         movaps  (%rsp),%xmm6
706         movaps  0x10(%rsp),%xmm7
707         movaps  0x20(%rsp),%xmm8
708         movaps  0x30(%rsp),%xmm9
709         lea     0x58(%rsp),%rsp
710 ___
711 $code.=<<___;
712 .Lcbc_ret:
713         ret
714 .size   ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt
715 ___
716 \f
717 # int $PREFIX_set_[en|de]crypt_key (const unsigned char *userKey,
718 #                               int bits, AES_KEY *key)
719 { my ($inp,$bits,$key) = @_4args;
720   $bits =~ s/%r/%e/;
721
722 $code.=<<___;
723 .globl  ${PREFIX}_set_decrypt_key
724 .type   ${PREFIX}_set_decrypt_key,\@abi-omnipotent
725 .align  16
726 ${PREFIX}_set_decrypt_key:
727         .byte   0x48,0x83,0xEC,0x08     # sub rsp,8
728         call    _aesni_set_encrypt_key
729         shl     \$4,$bits               # rounds-1 after _aesni_set_encrypt_key
730         test    %eax,%eax
731         jnz     .Ldec_key_ret
732         lea     16($key,$bits),$inp     # points at the end of key schedule
733
734         $movkey ($key),%xmm0            # just swap
735         $movkey ($inp),%xmm1
736         $movkey %xmm0,($inp)
737         $movkey %xmm1,($key)
738         lea     16($key),$key
739         lea     -16($inp),$inp
740
741 .Ldec_key_inverse:
742         $movkey ($key),%xmm0            # swap and inverse
743         $movkey ($inp),%xmm1
744         aesimc  %xmm0,%xmm0
745         aesimc  %xmm1,%xmm1
746         lea     16($key),$key
747         lea     -16($inp),$inp
748         cmp     $key,$inp
749         $movkey %xmm0,16($inp)
750         $movkey %xmm1,-16($key)
751         ja      .Ldec_key_inverse
752
753         $movkey ($key),%xmm0            # inverse middle
754         aesimc  %xmm0,%xmm0
755         $movkey %xmm0,($inp)
756 .Ldec_key_ret:
757         add     \$8,%rsp
758         ret
759 .LSEH_end_set_decrypt_key:
760 .size   ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key
761 ___
762 \f
763 # This is based on submission by
764 #
765 #       Huang Ying <ying.huang@intel.com>
766 #       Vinodh Gopal <vinodh.gopal@intel.com>
767 #       Kahraman Akdemir
768 #
769 # Agressively optimized in respect to aeskeygenassist's critical path
770 # and is contained in %xmm0-5 to meet Win64 ABI requirement.
771 #
772 $code.=<<___;
773 .globl  ${PREFIX}_set_encrypt_key
774 .type   ${PREFIX}_set_encrypt_key,\@abi-omnipotent
775 .align  16
776 ${PREFIX}_set_encrypt_key:
777 _aesni_set_encrypt_key:
778         .byte   0x48,0x83,0xEC,0x08     # sub rsp,8
779         test    $inp,$inp
780         mov     \$-1,%rax
781         jz      .Lenc_key_ret
782         test    $key,$key
783         jz      .Lenc_key_ret
784
785         movups  ($inp),%xmm0            # pull first 128 bits of *userKey
786         pxor    %xmm4,%xmm4             # low dword of xmm4 is assumed 0
787         lea     16($key),%rax
788         cmp     \$256,$bits
789         je      .L14rounds
790         cmp     \$192,$bits
791         je      .L12rounds
792         cmp     \$128,$bits
793         jne     .Lbad_keybits
794
795 .L10rounds:
796         mov     \$9,$bits                       # 10 rounds for 128-bit key
797         $movkey %xmm0,($key)                    # round 0
798         aeskeygenassist \$0x1,%xmm0,%xmm1       # round 1
799         call            .Lkey_expansion_128_cold
800         aeskeygenassist \$0x2,%xmm0,%xmm1       # round 2
801         call            .Lkey_expansion_128
802         aeskeygenassist \$0x4,%xmm0,%xmm1       # round 3
803         call            .Lkey_expansion_128
804         aeskeygenassist \$0x8,%xmm0,%xmm1       # round 4
805         call            .Lkey_expansion_128
806         aeskeygenassist \$0x10,%xmm0,%xmm1      # round 5
807         call            .Lkey_expansion_128
808         aeskeygenassist \$0x20,%xmm0,%xmm1      # round 6
809         call            .Lkey_expansion_128
810         aeskeygenassist \$0x40,%xmm0,%xmm1      # round 7
811         call            .Lkey_expansion_128
812         aeskeygenassist \$0x80,%xmm0,%xmm1      # round 8
813         call            .Lkey_expansion_128
814         aeskeygenassist \$0x1b,%xmm0,%xmm1      # round 9
815         call            .Lkey_expansion_128
816         aeskeygenassist \$0x36,%xmm0,%xmm1      # round 10
817         call            .Lkey_expansion_128
818         $movkey %xmm0,(%rax)
819         mov     $bits,80(%rax)  # 240(%rdx)
820         xor     %eax,%eax
821         jmp     .Lenc_key_ret
822
823 .align  16
824 .L12rounds:
825         movq    16($inp),%xmm2                  # remaining 1/3 of *userKey
826         mov     \$11,$bits                      # 12 rounds for 192
827         $movkey %xmm0,($key)                    # round 0
828         aeskeygenassist \$0x1,%xmm2,%xmm1       # round 1,2
829         call            .Lkey_expansion_192a_cold
830         aeskeygenassist \$0x2,%xmm2,%xmm1       # round 2,3
831         call            .Lkey_expansion_192b
832         aeskeygenassist \$0x4,%xmm2,%xmm1       # round 4,5
833         call            .Lkey_expansion_192a
834         aeskeygenassist \$0x8,%xmm2,%xmm1       # round 5,6
835         call            .Lkey_expansion_192b
836         aeskeygenassist \$0x10,%xmm2,%xmm1      # round 7,8
837         call            .Lkey_expansion_192a
838         aeskeygenassist \$0x20,%xmm2,%xmm1      # round 8,9
839         call            .Lkey_expansion_192b
840         aeskeygenassist \$0x40,%xmm2,%xmm1      # round 10,11
841         call            .Lkey_expansion_192a
842         aeskeygenassist \$0x80,%xmm2,%xmm1      # round 11,12
843         call            .Lkey_expansion_192b
844         $movkey %xmm0,(%rax)
845         mov     $bits,48(%rax)  # 240(%rdx)
846         xor     %rax, %rax
847         jmp     .Lenc_key_ret
848
849 .align  16
850 .L14rounds:
851         movups  16($inp),%xmm2                  # remaning half of *userKey
852         mov     \$13,$bits                      # 14 rounds for 256
853         lea     16(%rax),%rax
854         $movkey %xmm0,($key)                    # round 0
855         $movkey %xmm2,16($key)                  # round 1
856         aeskeygenassist \$0x1,%xmm2,%xmm1       # round 2
857         call            .Lkey_expansion_256a_cold
858         aeskeygenassist \$0x1,%xmm0,%xmm1       # round 3
859         call            .Lkey_expansion_256b
860         aeskeygenassist \$0x2,%xmm2,%xmm1       # round 4
861         call            .Lkey_expansion_256a
862         aeskeygenassist \$0x2,%xmm0,%xmm1       # round 5
863         call            .Lkey_expansion_256b
864         aeskeygenassist \$0x4,%xmm2,%xmm1       # round 6
865         call            .Lkey_expansion_256a
866         aeskeygenassist \$0x4,%xmm0,%xmm1       # round 7
867         call            .Lkey_expansion_256b
868         aeskeygenassist \$0x8,%xmm2,%xmm1       # round 8
869         call            .Lkey_expansion_256a
870         aeskeygenassist \$0x8,%xmm0,%xmm1       # round 9
871         call            .Lkey_expansion_256b
872         aeskeygenassist \$0x10,%xmm2,%xmm1      # round 10
873         call            .Lkey_expansion_256a
874         aeskeygenassist \$0x10,%xmm0,%xmm1      # round 11
875         call            .Lkey_expansion_256b
876         aeskeygenassist \$0x20,%xmm2,%xmm1      # round 12
877         call            .Lkey_expansion_256a
878         aeskeygenassist \$0x20,%xmm0,%xmm1      # round 13
879         call            .Lkey_expansion_256b
880         aeskeygenassist \$0x40,%xmm2,%xmm1      # round 14
881         call            .Lkey_expansion_256a
882         $movkey %xmm0,(%rax)
883         mov     $bits,16(%rax)  # 240(%rdx)
884         xor     %rax,%rax
885         jmp     .Lenc_key_ret
886
887 .align  16
888 .Lbad_keybits:
889         mov     \$-2,%rax
890 .Lenc_key_ret:
891         add     \$8,%rsp
892         ret
893 .LSEH_end_set_encrypt_key:
894 \f
895 .align  16
896 .Lkey_expansion_128:
897         $movkey %xmm0,(%rax)
898         lea     16(%rax),%rax
899 .Lkey_expansion_128_cold:
900         shufps  \$0b00010000,%xmm0,%xmm4
901         pxor    %xmm4, %xmm0
902         shufps  \$0b10001100,%xmm0,%xmm4
903         pxor    %xmm4, %xmm0
904         pshufd  \$0b11111111,%xmm1,%xmm1        # critical path
905         pxor    %xmm1,%xmm0
906         ret
907
908 .align 16
909 .Lkey_expansion_192a:
910         $movkey %xmm0,(%rax)
911         lea     16(%rax),%rax
912 .Lkey_expansion_192a_cold:
913         movaps  %xmm2, %xmm5
914 .Lkey_expansion_192b_warm:
915         shufps  \$0b00010000,%xmm0,%xmm4
916         movaps  %xmm2,%xmm3
917         pxor    %xmm4,%xmm0
918         shufps  \$0b10001100,%xmm0,%xmm4
919         pslldq  \$4,%xmm3
920         pxor    %xmm4,%xmm0
921         pshufd  \$0b01010101,%xmm1,%xmm1        # critical path
922         pxor    %xmm3,%xmm2
923         pxor    %xmm1,%xmm0
924         pshufd  \$0b11111111,%xmm0,%xmm3
925         pxor    %xmm3,%xmm2
926         ret
927
928 .align 16
929 .Lkey_expansion_192b:
930         movaps  %xmm0,%xmm3
931         shufps  \$0b01000100,%xmm0,%xmm5
932         $movkey %xmm5,(%rax)
933         shufps  \$0b01001110,%xmm2,%xmm3
934         $movkey %xmm3,16(%rax)
935         lea     32(%rax),%rax
936         jmp     .Lkey_expansion_192b_warm
937
938 .align  16
939 .Lkey_expansion_256a:
940         $movkey %xmm2,(%rax)
941         lea     16(%rax),%rax
942 .Lkey_expansion_256a_cold:
943         shufps  \$0b00010000,%xmm0,%xmm4
944         pxor    %xmm4,%xmm0
945         shufps  \$0b10001100,%xmm0,%xmm4
946         pxor    %xmm4,%xmm0
947         pshufd  \$0b11111111,%xmm1,%xmm1        # critical path
948         pxor    %xmm1,%xmm0
949         ret
950
951 .align 16
952 .Lkey_expansion_256b:
953         $movkey %xmm0,(%rax)
954         lea     16(%rax),%rax
955
956         shufps  \$0b00010000,%xmm2,%xmm4
957         pxor    %xmm4,%xmm2
958         shufps  \$0b10001100,%xmm2,%xmm4
959         pxor    %xmm4,%xmm2
960         pshufd  \$0b10101010,%xmm1,%xmm1        # critical path
961         pxor    %xmm1,%xmm2
962         ret
963 .size   ${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key
964 ___
965 }
966 \f
967 $code.=<<___;
968 .align  64
969 .Lbswap_mask:
970         .byte   15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
971 .Lincrement:
972         .long   3,3,3,0
973 .asciz  "AES for Intel AES-NI, CRYPTOGAMS by <appro\@openssl.org>"
974 .align  64
975 ___
976
977 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
978 #               CONTEXT *context,DISPATCHER_CONTEXT *disp)
979 if ($win64) {
980 $rec="%rcx";
981 $frame="%rdx";
982 $context="%r8";
983 $disp="%r9";
984
985 $code.=<<___;
986 .extern __imp_RtlVirtualUnwind
987 ___
988 $code.=<<___ if ($PREFIX eq "aesni");
989 .type   ecb_se_handler,\@abi-omnipotent
990 .align  16
991 ecb_se_handler:
992         push    %rsi
993         push    %rdi
994         push    %rbx
995         push    %rbp
996         push    %r12
997         push    %r13
998         push    %r14
999         push    %r15
1000         pushfq
1001         sub     \$64,%rsp
1002
1003         mov     152($context),%rax      # pull context->Rsp
1004         mov     8(%rax),%rdi
1005         mov     16(%rax),%rsi
1006         mov     %rsi,168($context)      # restore context->Rsi
1007         mov     %rdi,176($context)      # restore context->Rdi
1008
1009         jmp     .Lcommon_seh_exit
1010 .size   ecb_se_handler,.-ecb_se_handler
1011
1012 .type   ctr32_se_handler,\@abi-omnipotent
1013 .align  16
1014 ctr32_se_handler:
1015         push    %rsi
1016         push    %rdi
1017         push    %rbx
1018         push    %rbp
1019         push    %r12
1020         push    %r13
1021         push    %r14
1022         push    %r15
1023         pushfq
1024         sub     \$64,%rsp
1025
1026         mov     120($context),%rax      # pull context->Rax
1027         mov     248($context),%rbx      # pull context->Rip
1028
1029         lea     .Lctr32_body(%rip),%r10
1030         cmp     %r10,%rbx               # context->Rip<"prologue" label
1031         jb      .Lin_ctr32_prologue
1032
1033         mov     152($context),%rax      # pull context->Rsp
1034
1035         lea     .Lctr32_ret(%rip),%r10
1036         cmp     %r10,%rbx
1037         jae     .Lin_ctr32_prologue
1038
1039         lea     0(%rax),%rsi            # top of stack
1040         lea     512($context),%rdi      # &context.Xmm6
1041         mov     \$12,%ecx               # 6*sizeof(%xmm0)/sizeof(%rax)
1042         .long   0xa548f3fc              # cld; rep movsq
1043         lea     0x68(%rax),%rax         # adjust stack pointer
1044
1045 .Lin_ctr32_prologue:
1046         mov     8(%rax),%rdi
1047         mov     16(%rax),%rsi
1048         mov     %rax,152($context)      # restore context->Rsp
1049         mov     %rsi,168($context)      # restore context->Rsi
1050         mov     %rdi,176($context)      # restore context->Rdi
1051
1052         jmp     .Lcommon_seh_exit
1053 .size   ctr32_se_handler,.-ctr32_se_handler
1054 ___
1055 $code.=<<___;
1056 .type   cbc_se_handler,\@abi-omnipotent
1057 .align  16
1058 cbc_se_handler:
1059         push    %rsi
1060         push    %rdi
1061         push    %rbx
1062         push    %rbp
1063         push    %r12
1064         push    %r13
1065         push    %r14
1066         push    %r15
1067         pushfq
1068         sub     \$64,%rsp
1069
1070         mov     152($context),%rax      # pull context->Rsp
1071         mov     248($context),%rbx      # pull context->Rip
1072
1073         lea     .Lcbc_decrypt(%rip),%r10
1074         cmp     %r10,%rbx               # context->Rip<"prologue" label
1075         jb      .Lin_cbc_prologue
1076
1077         lea     .Lcbc_decrypt_body(%rip),%r10
1078         cmp     %r10,%rbx               # context->Rip<cbc_decrypt_body
1079         jb      .Lrestore_cbc_rax
1080
1081         lea     .Lcbc_ret(%rip),%r10
1082         cmp     %r10,%rbx               # context->Rip>="epilogue" label
1083         jae     .Lin_cbc_prologue
1084
1085         lea     0(%rax),%rsi            # top of stack
1086         lea     512($context),%rdi      # &context.Xmm6
1087         mov     \$8,%ecx                # 4*sizeof(%xmm0)/sizeof(%rax)
1088         .long   0xa548f3fc              # cld; rep movsq
1089         lea     0x58(%rax),%rax         # adjust stack pointer
1090         jmp     .Lin_cbc_prologue
1091
1092 .Lrestore_cbc_rax:
1093         mov     120($context),%rax
1094 .Lin_cbc_prologue:
1095         mov     8(%rax),%rdi
1096         mov     16(%rax),%rsi
1097         mov     %rax,152($context)      # restore context->Rsp
1098         mov     %rsi,168($context)      # restore context->Rsi
1099         mov     %rdi,176($context)      # restore context->Rdi
1100
1101 .Lcommon_seh_exit:
1102
1103         mov     40($disp),%rdi          # disp->ContextRecord
1104         mov     $context,%rsi           # context
1105         mov     \$154,%ecx              # sizeof(CONTEXT)
1106         .long   0xa548f3fc              # cld; rep movsq
1107
1108         mov     $disp,%rsi
1109         xor     %rcx,%rcx               # arg1, UNW_FLAG_NHANDLER
1110         mov     8(%rsi),%rdx            # arg2, disp->ImageBase
1111         mov     0(%rsi),%r8             # arg3, disp->ControlPc
1112         mov     16(%rsi),%r9            # arg4, disp->FunctionEntry
1113         mov     40(%rsi),%r10           # disp->ContextRecord
1114         lea     56(%rsi),%r11           # &disp->HandlerData
1115         lea     24(%rsi),%r12           # &disp->EstablisherFrame
1116         mov     %r10,32(%rsp)           # arg5
1117         mov     %r11,40(%rsp)           # arg6
1118         mov     %r12,48(%rsp)           # arg7
1119         mov     %rcx,56(%rsp)           # arg8, (NULL)
1120         call    *__imp_RtlVirtualUnwind(%rip)
1121
1122         mov     \$1,%eax                # ExceptionContinueSearch
1123         add     \$64,%rsp
1124         popfq
1125         pop     %r15
1126         pop     %r14
1127         pop     %r13
1128         pop     %r12
1129         pop     %rbp
1130         pop     %rbx
1131         pop     %rdi
1132         pop     %rsi
1133         ret
1134 .size   cbc_se_handler,.-cbc_se_handler
1135
1136 .section        .pdata
1137 .align  4
1138 ___
1139 $code.=<<___ if ($PREFIX eq "aesni");
1140         .rva    .LSEH_begin_aesni_ecb_encrypt
1141         .rva    .LSEH_end_aesni_ecb_encrypt
1142         .rva    .LSEH_info_ecb
1143
1144         .rva    .LSEH_begin_aesni_ctr32_encrypt_blocks
1145         .rva    .LSEH_end_aesni_ctr32_encrypt_blocks
1146         .rva    .LSEH_info_ctr32
1147 ___
1148 $code.=<<___;
1149         .rva    .LSEH_begin_${PREFIX}_cbc_encrypt
1150         .rva    .LSEH_end_${PREFIX}_cbc_encrypt
1151         .rva    .LSEH_info_cbc
1152
1153         .rva    ${PREFIX}_set_decrypt_key
1154         .rva    .LSEH_end_set_decrypt_key
1155         .rva    .LSEH_info_key
1156
1157         .rva    ${PREFIX}_set_encrypt_key
1158         .rva    .LSEH_end_set_encrypt_key
1159         .rva    .LSEH_info_key
1160 .section        .xdata
1161 .align  8
1162 ___
1163 $code.=<<___ if ($PREFIX eq "aesni");
1164 .LSEH_info_ecb:
1165         .byte   9,0,0,0
1166         .rva    ecb_se_handler
1167 .LSEH_info_ctr32:
1168         .byte   9,0,0,0
1169         .rva    ctr32_se_handler
1170 ___
1171 $code.=<<___;
1172 .LSEH_info_cbc:
1173         .byte   9,0,0,0
1174         .rva    cbc_se_handler
1175 .LSEH_info_key:
1176         .byte   0x01,0x04,0x01,0x00
1177         .byte   0x04,0x02,0x00,0x00
1178 ___
1179 }
1180
1181 sub rex {
1182  local *opcode=shift;
1183  my ($dst,$src)=@_;
1184
1185    if ($dst>=8 || $src>=8) {
1186         $rex=0x40;
1187         $rex|=0x04 if($dst>=8);
1188         $rex|=0x01 if($src>=8);
1189         push @opcode,$rex;
1190    }
1191 }
1192
1193 sub aesni {
1194   my $line=shift;
1195   my @opcode=(0x66);
1196
1197     if ($line=~/(aeskeygenassist)\s+\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
1198         rex(\@opcode,$4,$3);
1199         push @opcode,0x0f,0x3a,0xdf;
1200         push @opcode,0xc0|($3&7)|(($4&7)<<3);   # ModR/M
1201         my $c=$2;
1202         push @opcode,$c=~/^0/?oct($c):$c;
1203         return ".byte\t".join(',',@opcode);
1204     }
1205     elsif ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) {
1206         my %opcodelet = (
1207                 "aesimc" => 0xdb,
1208                 "aesenc" => 0xdc,       "aesenclast" => 0xdd,
1209                 "aesdec" => 0xde,       "aesdeclast" => 0xdf
1210         );
1211         return undef if (!defined($opcodelet{$1}));
1212         rex(\@opcode,$3,$2);
1213         push @opcode,0x0f,0x38,$opcodelet{$1};
1214         push @opcode,0xc0|($2&7)|(($3&7)<<3);   # ModR/M
1215         return ".byte\t".join(',',@opcode);
1216     }
1217     return $line;
1218 }
1219
1220 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
1221 $code =~ s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/gem;
1222
1223 print $code;
1224
1225 close STDOUT;