Import OpenSSL-1.0.1j.
[dragonfly.git] / crypto / openssl / 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 it's 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 # January 2011
83 #
84 # While Westmere processor features 6 cycles latency for aes[enc|dec]
85 # instructions, which can be scheduled every second cycle, Sandy
86 # Bridge spends 8 cycles per instruction, but it can schedule them
87 # every cycle. This means that code targeting Westmere would perform
88 # suboptimally on Sandy Bridge. Therefore this update.
89 #
90 # In addition, non-parallelizable CBC encrypt (as well as CCM) is
91 # optimized. Relative improvement might appear modest, 8% on Westmere,
92 # but in absolute terms it's 3.77 cycles per byte encrypted with
93 # 128-bit key on Westmere, and 5.07 - on Sandy Bridge. These numbers
94 # should be compared to asymptotic limits of 3.75 for Westmere and
95 # 5.00 for Sandy Bridge. Actually, the fact that they get this close
96 # to asymptotic limits is quite amazing. Indeed, the limit is
97 # calculated as latency times number of rounds, 10 for 128-bit key,
98 # and divided by 16, the number of bytes in block, or in other words
99 # it accounts *solely* for aesenc instructions. But there are extra
100 # instructions, and numbers so close to the asymptotic limits mean
101 # that it's as if it takes as little as *one* additional cycle to
102 # execute all of them. How is it possible? It is possible thanks to
103 # out-of-order execution logic, which manages to overlap post-
104 # processing of previous block, things like saving the output, with
105 # actual encryption of current block, as well as pre-processing of
106 # current block, things like fetching input and xor-ing it with
107 # 0-round element of the key schedule, with actual encryption of
108 # previous block. Keep this in mind...
109 #
110 # For parallelizable modes, such as ECB, CBC decrypt, CTR, higher
111 # performance is achieved by interleaving instructions working on
112 # independent blocks. In which case asymptotic limit for such modes
113 # can be obtained by dividing above mentioned numbers by AES
114 # instructions' interleave factor. Westmere can execute at most 3 
115 # instructions at a time, meaning that optimal interleave factor is 3,
116 # and that's where the "magic" number of 1.25 come from. "Optimal
117 # interleave factor" means that increase of interleave factor does
118 # not improve performance. The formula has proven to reflect reality
119 # pretty well on Westmere... Sandy Bridge on the other hand can
120 # execute up to 8 AES instructions at a time, so how does varying
121 # interleave factor affect the performance? Here is table for ECB
122 # (numbers are cycles per byte processed with 128-bit key):
123 #
124 # instruction interleave factor         3x      6x      8x
125 # theoretical asymptotic limit          1.67    0.83    0.625
126 # measured performance for 8KB block    1.05    0.86    0.84
127 #
128 # "as if" interleave factor             4.7x    5.8x    6.0x
129 #
130 # Further data for other parallelizable modes:
131 #
132 # CBC decrypt                           1.16    0.93    0.93
133 # CTR                                   1.14    0.91    n/a
134 #
135 # Well, given 3x column it's probably inappropriate to call the limit
136 # asymptotic, if it can be surpassed, isn't it? What happens there?
137 # Rewind to CBC paragraph for the answer. Yes, out-of-order execution
138 # magic is responsible for this. Processor overlaps not only the
139 # additional instructions with AES ones, but even AES instuctions
140 # processing adjacent triplets of independent blocks. In the 6x case
141 # additional instructions  still claim disproportionally small amount
142 # of additional cycles, but in 8x case number of instructions must be
143 # a tad too high for out-of-order logic to cope with, and AES unit
144 # remains underutilized... As you can see 8x interleave is hardly
145 # justifiable, so there no need to feel bad that 32-bit aesni-x86.pl
146 # utilizies 6x interleave because of limited register bank capacity.
147 #
148 # Higher interleave factors do have negative impact on Westmere
149 # performance. While for ECB mode it's negligible ~1.5%, other
150 # parallelizables perform ~5% worse, which is outweighed by ~25%
151 # improvement on Sandy Bridge. To balance regression on Westmere
152 # CTR mode was implemented with 6x aesenc interleave factor.
153
154 # April 2011
155 #
156 # Add aesni_xts_[en|de]crypt. Westmere spends 1.33 cycles processing
157 # one byte out of 8KB with 128-bit key, Sandy Bridge - 0.97. Just like
158 # in CTR mode AES instruction interleave factor was chosen to be 6x.
159
160 $PREFIX="aesni";        # if $PREFIX is set to "AES", the script
161                         # generates drop-in replacement for
162                         # crypto/aes/asm/aes-x86_64.pl:-)
163
164 $flavour = shift;
165 $output  = shift;
166 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
167
168 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
169
170 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
171 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
172 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
173 die "can't locate x86_64-xlate.pl";
174
175 open OUT,"| \"$^X\" $xlate $flavour $output";
176 *STDOUT=*OUT;
177
178 $movkey = $PREFIX eq "aesni" ? "movups" : "movups";
179 @_4args=$win64? ("%rcx","%rdx","%r8", "%r9") :  # Win64 order
180                 ("%rdi","%rsi","%rdx","%rcx");  # Unix order
181
182 $code=".text\n";
183
184 $rounds="%eax"; # input to and changed by aesni_[en|de]cryptN !!!
185 # this is natural Unix argument order for public $PREFIX_[ecb|cbc]_encrypt ...
186 $inp="%rdi";
187 $out="%rsi";
188 $len="%rdx";
189 $key="%rcx";    # input to and changed by aesni_[en|de]cryptN !!!
190 $ivp="%r8";     # cbc, ctr, ...
191
192 $rnds_="%r10d"; # backup copy for $rounds
193 $key_="%r11";   # backup copy for $key
194
195 # %xmm register layout
196 $rndkey0="%xmm0";       $rndkey1="%xmm1";
197 $inout0="%xmm2";        $inout1="%xmm3";
198 $inout2="%xmm4";        $inout3="%xmm5";
199 $inout4="%xmm6";        $inout5="%xmm7";
200 $inout6="%xmm8";        $inout7="%xmm9";
201
202 $in2="%xmm6";           $in1="%xmm7";   # used in CBC decrypt, CTR, ...
203 $in0="%xmm8";           $iv="%xmm9";
204 \f
205 # Inline version of internal aesni_[en|de]crypt1.
206 #
207 # Why folded loop? Because aes[enc|dec] is slow enough to accommodate
208 # cycles which take care of loop variables...
209 { my $sn;
210 sub aesni_generate1 {
211 my ($p,$key,$rounds,$inout,$ivec)=@_;   $inout=$inout0 if (!defined($inout));
212 ++$sn;
213 $code.=<<___;
214         $movkey ($key),$rndkey0
215         $movkey 16($key),$rndkey1
216 ___
217 $code.=<<___ if (defined($ivec));
218         xorps   $rndkey0,$ivec
219         lea     32($key),$key
220         xorps   $ivec,$inout
221 ___
222 $code.=<<___ if (!defined($ivec));
223         lea     32($key),$key
224         xorps   $rndkey0,$inout
225 ___
226 $code.=<<___;
227 .Loop_${p}1_$sn:
228         aes${p} $rndkey1,$inout
229         dec     $rounds
230         $movkey ($key),$rndkey1
231         lea     16($key),$key
232         jnz     .Loop_${p}1_$sn # loop body is 16 bytes
233         aes${p}last     $rndkey1,$inout
234 ___
235 }}
236 # void $PREFIX_[en|de]crypt (const void *inp,void *out,const AES_KEY *key);
237 #
238 { my ($inp,$out,$key) = @_4args;
239
240 $code.=<<___;
241 .globl  ${PREFIX}_encrypt
242 .type   ${PREFIX}_encrypt,\@abi-omnipotent
243 .align  16
244 ${PREFIX}_encrypt:
245         movups  ($inp),$inout0          # load input
246         mov     240($key),$rounds       # key->rounds
247 ___
248         &aesni_generate1("enc",$key,$rounds);
249 $code.=<<___;
250         movups  $inout0,($out)          # output
251         ret
252 .size   ${PREFIX}_encrypt,.-${PREFIX}_encrypt
253
254 .globl  ${PREFIX}_decrypt
255 .type   ${PREFIX}_decrypt,\@abi-omnipotent
256 .align  16
257 ${PREFIX}_decrypt:
258         movups  ($inp),$inout0          # load input
259         mov     240($key),$rounds       # key->rounds
260 ___
261         &aesni_generate1("dec",$key,$rounds);
262 $code.=<<___;
263         movups  $inout0,($out)          # output
264         ret
265 .size   ${PREFIX}_decrypt, .-${PREFIX}_decrypt
266 ___
267 }
268 \f
269 # _aesni_[en|de]cryptN are private interfaces, N denotes interleave
270 # factor. Why 3x subroutine were originally used in loops? Even though
271 # aes[enc|dec] latency was originally 6, it could be scheduled only
272 # every *2nd* cycle. Thus 3x interleave was the one providing optimal
273 # utilization, i.e. when subroutine's throughput is virtually same as
274 # of non-interleaved subroutine [for number of input blocks up to 3].
275 # This is why it makes no sense to implement 2x subroutine.
276 # aes[enc|dec] latency in next processor generation is 8, but the
277 # instructions can be scheduled every cycle. Optimal interleave for
278 # new processor is therefore 8x...
279 sub aesni_generate3 {
280 my $dir=shift;
281 # As already mentioned it takes in $key and $rounds, which are *not*
282 # preserved. $inout[0-2] is cipher/clear text...
283 $code.=<<___;
284 .type   _aesni_${dir}rypt3,\@abi-omnipotent
285 .align  16
286 _aesni_${dir}rypt3:
287         $movkey ($key),$rndkey0
288         shr     \$1,$rounds
289         $movkey 16($key),$rndkey1
290         lea     32($key),$key
291         xorps   $rndkey0,$inout0
292         xorps   $rndkey0,$inout1
293         xorps   $rndkey0,$inout2
294         $movkey         ($key),$rndkey0
295
296 .L${dir}_loop3:
297         aes${dir}       $rndkey1,$inout0
298         aes${dir}       $rndkey1,$inout1
299         dec             $rounds
300         aes${dir}       $rndkey1,$inout2
301         $movkey         16($key),$rndkey1
302         aes${dir}       $rndkey0,$inout0
303         aes${dir}       $rndkey0,$inout1
304         lea             32($key),$key
305         aes${dir}       $rndkey0,$inout2
306         $movkey         ($key),$rndkey0
307         jnz             .L${dir}_loop3
308
309         aes${dir}       $rndkey1,$inout0
310         aes${dir}       $rndkey1,$inout1
311         aes${dir}       $rndkey1,$inout2
312         aes${dir}last   $rndkey0,$inout0
313         aes${dir}last   $rndkey0,$inout1
314         aes${dir}last   $rndkey0,$inout2
315         ret
316 .size   _aesni_${dir}rypt3,.-_aesni_${dir}rypt3
317 ___
318 }
319 # 4x interleave is implemented to improve small block performance,
320 # most notably [and naturally] 4 block by ~30%. One can argue that one
321 # should have implemented 5x as well, but improvement would be <20%,
322 # so it's not worth it...
323 sub aesni_generate4 {
324 my $dir=shift;
325 # As already mentioned it takes in $key and $rounds, which are *not*
326 # preserved. $inout[0-3] is cipher/clear text...
327 $code.=<<___;
328 .type   _aesni_${dir}rypt4,\@abi-omnipotent
329 .align  16
330 _aesni_${dir}rypt4:
331         $movkey ($key),$rndkey0
332         shr     \$1,$rounds
333         $movkey 16($key),$rndkey1
334         lea     32($key),$key
335         xorps   $rndkey0,$inout0
336         xorps   $rndkey0,$inout1
337         xorps   $rndkey0,$inout2
338         xorps   $rndkey0,$inout3
339         $movkey ($key),$rndkey0
340
341 .L${dir}_loop4:
342         aes${dir}       $rndkey1,$inout0
343         aes${dir}       $rndkey1,$inout1
344         dec             $rounds
345         aes${dir}       $rndkey1,$inout2
346         aes${dir}       $rndkey1,$inout3
347         $movkey         16($key),$rndkey1
348         aes${dir}       $rndkey0,$inout0
349         aes${dir}       $rndkey0,$inout1
350         lea             32($key),$key
351         aes${dir}       $rndkey0,$inout2
352         aes${dir}       $rndkey0,$inout3
353         $movkey         ($key),$rndkey0
354         jnz             .L${dir}_loop4
355
356         aes${dir}       $rndkey1,$inout0
357         aes${dir}       $rndkey1,$inout1
358         aes${dir}       $rndkey1,$inout2
359         aes${dir}       $rndkey1,$inout3
360         aes${dir}last   $rndkey0,$inout0
361         aes${dir}last   $rndkey0,$inout1
362         aes${dir}last   $rndkey0,$inout2
363         aes${dir}last   $rndkey0,$inout3
364         ret
365 .size   _aesni_${dir}rypt4,.-_aesni_${dir}rypt4
366 ___
367 }
368 sub aesni_generate6 {
369 my $dir=shift;
370 # As already mentioned it takes in $key and $rounds, which are *not*
371 # preserved. $inout[0-5] is cipher/clear text...
372 $code.=<<___;
373 .type   _aesni_${dir}rypt6,\@abi-omnipotent
374 .align  16
375 _aesni_${dir}rypt6:
376         $movkey         ($key),$rndkey0
377         shr             \$1,$rounds
378         $movkey         16($key),$rndkey1
379         lea             32($key),$key
380         xorps           $rndkey0,$inout0
381         pxor            $rndkey0,$inout1
382         aes${dir}       $rndkey1,$inout0
383         pxor            $rndkey0,$inout2
384         aes${dir}       $rndkey1,$inout1
385         pxor            $rndkey0,$inout3
386         aes${dir}       $rndkey1,$inout2
387         pxor            $rndkey0,$inout4
388         aes${dir}       $rndkey1,$inout3
389         pxor            $rndkey0,$inout5
390         dec             $rounds
391         aes${dir}       $rndkey1,$inout4
392         $movkey         ($key),$rndkey0
393         aes${dir}       $rndkey1,$inout5
394         jmp             .L${dir}_loop6_enter
395 .align  16
396 .L${dir}_loop6:
397         aes${dir}       $rndkey1,$inout0
398         aes${dir}       $rndkey1,$inout1
399         dec             $rounds
400         aes${dir}       $rndkey1,$inout2
401         aes${dir}       $rndkey1,$inout3
402         aes${dir}       $rndkey1,$inout4
403         aes${dir}       $rndkey1,$inout5
404 .L${dir}_loop6_enter:                           # happens to be 16-byte aligned
405         $movkey         16($key),$rndkey1
406         aes${dir}       $rndkey0,$inout0
407         aes${dir}       $rndkey0,$inout1
408         lea             32($key),$key
409         aes${dir}       $rndkey0,$inout2
410         aes${dir}       $rndkey0,$inout3
411         aes${dir}       $rndkey0,$inout4
412         aes${dir}       $rndkey0,$inout5
413         $movkey         ($key),$rndkey0
414         jnz             .L${dir}_loop6
415
416         aes${dir}       $rndkey1,$inout0
417         aes${dir}       $rndkey1,$inout1
418         aes${dir}       $rndkey1,$inout2
419         aes${dir}       $rndkey1,$inout3
420         aes${dir}       $rndkey1,$inout4
421         aes${dir}       $rndkey1,$inout5
422         aes${dir}last   $rndkey0,$inout0
423         aes${dir}last   $rndkey0,$inout1
424         aes${dir}last   $rndkey0,$inout2
425         aes${dir}last   $rndkey0,$inout3
426         aes${dir}last   $rndkey0,$inout4
427         aes${dir}last   $rndkey0,$inout5
428         ret
429 .size   _aesni_${dir}rypt6,.-_aesni_${dir}rypt6
430 ___
431 }
432 sub aesni_generate8 {
433 my $dir=shift;
434 # As already mentioned it takes in $key and $rounds, which are *not*
435 # preserved. $inout[0-7] is cipher/clear text...
436 $code.=<<___;
437 .type   _aesni_${dir}rypt8,\@abi-omnipotent
438 .align  16
439 _aesni_${dir}rypt8:
440         $movkey         ($key),$rndkey0
441         shr             \$1,$rounds
442         $movkey         16($key),$rndkey1
443         lea             32($key),$key
444         xorps           $rndkey0,$inout0
445         xorps           $rndkey0,$inout1
446         aes${dir}       $rndkey1,$inout0
447         pxor            $rndkey0,$inout2
448         aes${dir}       $rndkey1,$inout1
449         pxor            $rndkey0,$inout3
450         aes${dir}       $rndkey1,$inout2
451         pxor            $rndkey0,$inout4
452         aes${dir}       $rndkey1,$inout3
453         pxor            $rndkey0,$inout5
454         dec             $rounds
455         aes${dir}       $rndkey1,$inout4
456         pxor            $rndkey0,$inout6
457         aes${dir}       $rndkey1,$inout5
458         pxor            $rndkey0,$inout7
459         $movkey         ($key),$rndkey0
460         aes${dir}       $rndkey1,$inout6
461         aes${dir}       $rndkey1,$inout7
462         $movkey         16($key),$rndkey1
463         jmp             .L${dir}_loop8_enter
464 .align  16
465 .L${dir}_loop8:
466         aes${dir}       $rndkey1,$inout0
467         aes${dir}       $rndkey1,$inout1
468         dec             $rounds
469         aes${dir}       $rndkey1,$inout2
470         aes${dir}       $rndkey1,$inout3
471         aes${dir}       $rndkey1,$inout4
472         aes${dir}       $rndkey1,$inout5
473         aes${dir}       $rndkey1,$inout6
474         aes${dir}       $rndkey1,$inout7
475         $movkey         16($key),$rndkey1
476 .L${dir}_loop8_enter:                           # happens to be 16-byte aligned
477         aes${dir}       $rndkey0,$inout0
478         aes${dir}       $rndkey0,$inout1
479         lea             32($key),$key
480         aes${dir}       $rndkey0,$inout2
481         aes${dir}       $rndkey0,$inout3
482         aes${dir}       $rndkey0,$inout4
483         aes${dir}       $rndkey0,$inout5
484         aes${dir}       $rndkey0,$inout6
485         aes${dir}       $rndkey0,$inout7
486         $movkey         ($key),$rndkey0
487         jnz             .L${dir}_loop8
488
489         aes${dir}       $rndkey1,$inout0
490         aes${dir}       $rndkey1,$inout1
491         aes${dir}       $rndkey1,$inout2
492         aes${dir}       $rndkey1,$inout3
493         aes${dir}       $rndkey1,$inout4
494         aes${dir}       $rndkey1,$inout5
495         aes${dir}       $rndkey1,$inout6
496         aes${dir}       $rndkey1,$inout7
497         aes${dir}last   $rndkey0,$inout0
498         aes${dir}last   $rndkey0,$inout1
499         aes${dir}last   $rndkey0,$inout2
500         aes${dir}last   $rndkey0,$inout3
501         aes${dir}last   $rndkey0,$inout4
502         aes${dir}last   $rndkey0,$inout5
503         aes${dir}last   $rndkey0,$inout6
504         aes${dir}last   $rndkey0,$inout7
505         ret
506 .size   _aesni_${dir}rypt8,.-_aesni_${dir}rypt8
507 ___
508 }
509 &aesni_generate3("enc") if ($PREFIX eq "aesni");
510 &aesni_generate3("dec");
511 &aesni_generate4("enc") if ($PREFIX eq "aesni");
512 &aesni_generate4("dec");
513 &aesni_generate6("enc") if ($PREFIX eq "aesni");
514 &aesni_generate6("dec");
515 &aesni_generate8("enc") if ($PREFIX eq "aesni");
516 &aesni_generate8("dec");
517 \f
518 if ($PREFIX eq "aesni") {
519 ########################################################################
520 # void aesni_ecb_encrypt (const void *in, void *out,
521 #                         size_t length, const AES_KEY *key,
522 #                         int enc);
523 $code.=<<___;
524 .globl  aesni_ecb_encrypt
525 .type   aesni_ecb_encrypt,\@function,5
526 .align  16
527 aesni_ecb_encrypt:
528 ___
529 $code.=<<___ if ($win64);
530         lea     -0x58(%rsp),%rsp
531         movaps  %xmm6,(%rsp)
532         movaps  %xmm7,0x10(%rsp)
533         movaps  %xmm8,0x20(%rsp)
534         movaps  %xmm9,0x30(%rsp)
535 .Lecb_enc_body:
536 ___
537 $code.=<<___;
538         and     \$-16,$len
539         jz      .Lecb_ret
540
541         mov     240($key),$rounds       # key->rounds
542         $movkey ($key),$rndkey0
543         mov     $key,$key_              # backup $key
544         mov     $rounds,$rnds_          # backup $rounds
545         test    %r8d,%r8d               # 5th argument
546         jz      .Lecb_decrypt
547 #--------------------------- ECB ENCRYPT ------------------------------#
548         cmp     \$0x80,$len
549         jb      .Lecb_enc_tail
550
551         movdqu  ($inp),$inout0
552         movdqu  0x10($inp),$inout1
553         movdqu  0x20($inp),$inout2
554         movdqu  0x30($inp),$inout3
555         movdqu  0x40($inp),$inout4
556         movdqu  0x50($inp),$inout5
557         movdqu  0x60($inp),$inout6
558         movdqu  0x70($inp),$inout7
559         lea     0x80($inp),$inp
560         sub     \$0x80,$len
561         jmp     .Lecb_enc_loop8_enter
562 .align 16
563 .Lecb_enc_loop8:
564         movups  $inout0,($out)
565         mov     $key_,$key              # restore $key
566         movdqu  ($inp),$inout0
567         mov     $rnds_,$rounds          # restore $rounds
568         movups  $inout1,0x10($out)
569         movdqu  0x10($inp),$inout1
570         movups  $inout2,0x20($out)
571         movdqu  0x20($inp),$inout2
572         movups  $inout3,0x30($out)
573         movdqu  0x30($inp),$inout3
574         movups  $inout4,0x40($out)
575         movdqu  0x40($inp),$inout4
576         movups  $inout5,0x50($out)
577         movdqu  0x50($inp),$inout5
578         movups  $inout6,0x60($out)
579         movdqu  0x60($inp),$inout6
580         movups  $inout7,0x70($out)
581         lea     0x80($out),$out
582         movdqu  0x70($inp),$inout7
583         lea     0x80($inp),$inp
584 .Lecb_enc_loop8_enter:
585
586         call    _aesni_encrypt8
587
588         sub     \$0x80,$len
589         jnc     .Lecb_enc_loop8
590
591         movups  $inout0,($out)
592         mov     $key_,$key              # restore $key
593         movups  $inout1,0x10($out)
594         mov     $rnds_,$rounds          # restore $rounds
595         movups  $inout2,0x20($out)
596         movups  $inout3,0x30($out)
597         movups  $inout4,0x40($out)
598         movups  $inout5,0x50($out)
599         movups  $inout6,0x60($out)
600         movups  $inout7,0x70($out)
601         lea     0x80($out),$out
602         add     \$0x80,$len
603         jz      .Lecb_ret
604
605 .Lecb_enc_tail:
606         movups  ($inp),$inout0
607         cmp     \$0x20,$len
608         jb      .Lecb_enc_one
609         movups  0x10($inp),$inout1
610         je      .Lecb_enc_two
611         movups  0x20($inp),$inout2
612         cmp     \$0x40,$len
613         jb      .Lecb_enc_three
614         movups  0x30($inp),$inout3
615         je      .Lecb_enc_four
616         movups  0x40($inp),$inout4
617         cmp     \$0x60,$len
618         jb      .Lecb_enc_five
619         movups  0x50($inp),$inout5
620         je      .Lecb_enc_six
621         movdqu  0x60($inp),$inout6
622         call    _aesni_encrypt8
623         movups  $inout0,($out)
624         movups  $inout1,0x10($out)
625         movups  $inout2,0x20($out)
626         movups  $inout3,0x30($out)
627         movups  $inout4,0x40($out)
628         movups  $inout5,0x50($out)
629         movups  $inout6,0x60($out)
630         jmp     .Lecb_ret
631 .align  16
632 .Lecb_enc_one:
633 ___
634         &aesni_generate1("enc",$key,$rounds);
635 $code.=<<___;
636         movups  $inout0,($out)
637         jmp     .Lecb_ret
638 .align  16
639 .Lecb_enc_two:
640         xorps   $inout2,$inout2
641         call    _aesni_encrypt3
642         movups  $inout0,($out)
643         movups  $inout1,0x10($out)
644         jmp     .Lecb_ret
645 .align  16
646 .Lecb_enc_three:
647         call    _aesni_encrypt3
648         movups  $inout0,($out)
649         movups  $inout1,0x10($out)
650         movups  $inout2,0x20($out)
651         jmp     .Lecb_ret
652 .align  16
653 .Lecb_enc_four:
654         call    _aesni_encrypt4
655         movups  $inout0,($out)
656         movups  $inout1,0x10($out)
657         movups  $inout2,0x20($out)
658         movups  $inout3,0x30($out)
659         jmp     .Lecb_ret
660 .align  16
661 .Lecb_enc_five:
662         xorps   $inout5,$inout5
663         call    _aesni_encrypt6
664         movups  $inout0,($out)
665         movups  $inout1,0x10($out)
666         movups  $inout2,0x20($out)
667         movups  $inout3,0x30($out)
668         movups  $inout4,0x40($out)
669         jmp     .Lecb_ret
670 .align  16
671 .Lecb_enc_six:
672         call    _aesni_encrypt6
673         movups  $inout0,($out)
674         movups  $inout1,0x10($out)
675         movups  $inout2,0x20($out)
676         movups  $inout3,0x30($out)
677         movups  $inout4,0x40($out)
678         movups  $inout5,0x50($out)
679         jmp     .Lecb_ret
680 \f#--------------------------- ECB DECRYPT ------------------------------#
681 .align  16
682 .Lecb_decrypt:
683         cmp     \$0x80,$len
684         jb      .Lecb_dec_tail
685
686         movdqu  ($inp),$inout0
687         movdqu  0x10($inp),$inout1
688         movdqu  0x20($inp),$inout2
689         movdqu  0x30($inp),$inout3
690         movdqu  0x40($inp),$inout4
691         movdqu  0x50($inp),$inout5
692         movdqu  0x60($inp),$inout6
693         movdqu  0x70($inp),$inout7
694         lea     0x80($inp),$inp
695         sub     \$0x80,$len
696         jmp     .Lecb_dec_loop8_enter
697 .align 16
698 .Lecb_dec_loop8:
699         movups  $inout0,($out)
700         mov     $key_,$key              # restore $key
701         movdqu  ($inp),$inout0
702         mov     $rnds_,$rounds          # restore $rounds
703         movups  $inout1,0x10($out)
704         movdqu  0x10($inp),$inout1
705         movups  $inout2,0x20($out)
706         movdqu  0x20($inp),$inout2
707         movups  $inout3,0x30($out)
708         movdqu  0x30($inp),$inout3
709         movups  $inout4,0x40($out)
710         movdqu  0x40($inp),$inout4
711         movups  $inout5,0x50($out)
712         movdqu  0x50($inp),$inout5
713         movups  $inout6,0x60($out)
714         movdqu  0x60($inp),$inout6
715         movups  $inout7,0x70($out)
716         lea     0x80($out),$out
717         movdqu  0x70($inp),$inout7
718         lea     0x80($inp),$inp
719 .Lecb_dec_loop8_enter:
720
721         call    _aesni_decrypt8
722
723         $movkey ($key_),$rndkey0
724         sub     \$0x80,$len
725         jnc     .Lecb_dec_loop8
726
727         movups  $inout0,($out)
728         mov     $key_,$key              # restore $key
729         movups  $inout1,0x10($out)
730         mov     $rnds_,$rounds          # restore $rounds
731         movups  $inout2,0x20($out)
732         movups  $inout3,0x30($out)
733         movups  $inout4,0x40($out)
734         movups  $inout5,0x50($out)
735         movups  $inout6,0x60($out)
736         movups  $inout7,0x70($out)
737         lea     0x80($out),$out
738         add     \$0x80,$len
739         jz      .Lecb_ret
740
741 .Lecb_dec_tail:
742         movups  ($inp),$inout0
743         cmp     \$0x20,$len
744         jb      .Lecb_dec_one
745         movups  0x10($inp),$inout1
746         je      .Lecb_dec_two
747         movups  0x20($inp),$inout2
748         cmp     \$0x40,$len
749         jb      .Lecb_dec_three
750         movups  0x30($inp),$inout3
751         je      .Lecb_dec_four
752         movups  0x40($inp),$inout4
753         cmp     \$0x60,$len
754         jb      .Lecb_dec_five
755         movups  0x50($inp),$inout5
756         je      .Lecb_dec_six
757         movups  0x60($inp),$inout6
758         $movkey ($key),$rndkey0
759         call    _aesni_decrypt8
760         movups  $inout0,($out)
761         movups  $inout1,0x10($out)
762         movups  $inout2,0x20($out)
763         movups  $inout3,0x30($out)
764         movups  $inout4,0x40($out)
765         movups  $inout5,0x50($out)
766         movups  $inout6,0x60($out)
767         jmp     .Lecb_ret
768 .align  16
769 .Lecb_dec_one:
770 ___
771         &aesni_generate1("dec",$key,$rounds);
772 $code.=<<___;
773         movups  $inout0,($out)
774         jmp     .Lecb_ret
775 .align  16
776 .Lecb_dec_two:
777         xorps   $inout2,$inout2
778         call    _aesni_decrypt3
779         movups  $inout0,($out)
780         movups  $inout1,0x10($out)
781         jmp     .Lecb_ret
782 .align  16
783 .Lecb_dec_three:
784         call    _aesni_decrypt3
785         movups  $inout0,($out)
786         movups  $inout1,0x10($out)
787         movups  $inout2,0x20($out)
788         jmp     .Lecb_ret
789 .align  16
790 .Lecb_dec_four:
791         call    _aesni_decrypt4
792         movups  $inout0,($out)
793         movups  $inout1,0x10($out)
794         movups  $inout2,0x20($out)
795         movups  $inout3,0x30($out)
796         jmp     .Lecb_ret
797 .align  16
798 .Lecb_dec_five:
799         xorps   $inout5,$inout5
800         call    _aesni_decrypt6
801         movups  $inout0,($out)
802         movups  $inout1,0x10($out)
803         movups  $inout2,0x20($out)
804         movups  $inout3,0x30($out)
805         movups  $inout4,0x40($out)
806         jmp     .Lecb_ret
807 .align  16
808 .Lecb_dec_six:
809         call    _aesni_decrypt6
810         movups  $inout0,($out)
811         movups  $inout1,0x10($out)
812         movups  $inout2,0x20($out)
813         movups  $inout3,0x30($out)
814         movups  $inout4,0x40($out)
815         movups  $inout5,0x50($out)
816
817 .Lecb_ret:
818 ___
819 $code.=<<___ if ($win64);
820         movaps  (%rsp),%xmm6
821         movaps  0x10(%rsp),%xmm7
822         movaps  0x20(%rsp),%xmm8
823         movaps  0x30(%rsp),%xmm9
824         lea     0x58(%rsp),%rsp
825 .Lecb_enc_ret:
826 ___
827 $code.=<<___;
828         ret
829 .size   aesni_ecb_encrypt,.-aesni_ecb_encrypt
830 ___
831 \f
832 {
833 ######################################################################
834 # void aesni_ccm64_[en|de]crypt_blocks (const void *in, void *out,
835 #                         size_t blocks, const AES_KEY *key,
836 #                         const char *ivec,char *cmac);
837 #
838 # Handles only complete blocks, operates on 64-bit counter and
839 # does not update *ivec! Nor does it finalize CMAC value
840 # (see engine/eng_aesni.c for details)
841 #
842 {
843 my $cmac="%r9"; # 6th argument
844
845 my $increment="%xmm6";
846 my $bswap_mask="%xmm7";
847
848 $code.=<<___;
849 .globl  aesni_ccm64_encrypt_blocks
850 .type   aesni_ccm64_encrypt_blocks,\@function,6
851 .align  16
852 aesni_ccm64_encrypt_blocks:
853 ___
854 $code.=<<___ if ($win64);
855         lea     -0x58(%rsp),%rsp
856         movaps  %xmm6,(%rsp)
857         movaps  %xmm7,0x10(%rsp)
858         movaps  %xmm8,0x20(%rsp)
859         movaps  %xmm9,0x30(%rsp)
860 .Lccm64_enc_body:
861 ___
862 $code.=<<___;
863         mov     240($key),$rounds               # key->rounds
864         movdqu  ($ivp),$iv
865         movdqa  .Lincrement64(%rip),$increment
866         movdqa  .Lbswap_mask(%rip),$bswap_mask
867
868         shr     \$1,$rounds
869         lea     0($key),$key_
870         movdqu  ($cmac),$inout1
871         movdqa  $iv,$inout0
872         mov     $rounds,$rnds_
873         pshufb  $bswap_mask,$iv
874         jmp     .Lccm64_enc_outer
875 .align  16
876 .Lccm64_enc_outer:
877         $movkey ($key_),$rndkey0
878         mov     $rnds_,$rounds
879         movups  ($inp),$in0                     # load inp
880
881         xorps   $rndkey0,$inout0                # counter
882         $movkey 16($key_),$rndkey1
883         xorps   $in0,$rndkey0
884         lea     32($key_),$key
885         xorps   $rndkey0,$inout1                # cmac^=inp
886         $movkey ($key),$rndkey0
887
888 .Lccm64_enc2_loop:
889         aesenc  $rndkey1,$inout0
890         dec     $rounds
891         aesenc  $rndkey1,$inout1
892         $movkey 16($key),$rndkey1
893         aesenc  $rndkey0,$inout0
894         lea     32($key),$key
895         aesenc  $rndkey0,$inout1
896         $movkey 0($key),$rndkey0
897         jnz     .Lccm64_enc2_loop
898         aesenc  $rndkey1,$inout0
899         aesenc  $rndkey1,$inout1
900         paddq   $increment,$iv
901         aesenclast      $rndkey0,$inout0
902         aesenclast      $rndkey0,$inout1
903
904         dec     $len
905         lea     16($inp),$inp
906         xorps   $inout0,$in0                    # inp ^= E(iv)
907         movdqa  $iv,$inout0
908         movups  $in0,($out)                     # save output
909         lea     16($out),$out
910         pshufb  $bswap_mask,$inout0
911         jnz     .Lccm64_enc_outer
912
913         movups  $inout1,($cmac)
914 ___
915 $code.=<<___ if ($win64);
916         movaps  (%rsp),%xmm6
917         movaps  0x10(%rsp),%xmm7
918         movaps  0x20(%rsp),%xmm8
919         movaps  0x30(%rsp),%xmm9
920         lea     0x58(%rsp),%rsp
921 .Lccm64_enc_ret:
922 ___
923 $code.=<<___;
924         ret
925 .size   aesni_ccm64_encrypt_blocks,.-aesni_ccm64_encrypt_blocks
926 ___
927 ######################################################################
928 $code.=<<___;
929 .globl  aesni_ccm64_decrypt_blocks
930 .type   aesni_ccm64_decrypt_blocks,\@function,6
931 .align  16
932 aesni_ccm64_decrypt_blocks:
933 ___
934 $code.=<<___ if ($win64);
935         lea     -0x58(%rsp),%rsp
936         movaps  %xmm6,(%rsp)
937         movaps  %xmm7,0x10(%rsp)
938         movaps  %xmm8,0x20(%rsp)
939         movaps  %xmm9,0x30(%rsp)
940 .Lccm64_dec_body:
941 ___
942 $code.=<<___;
943         mov     240($key),$rounds               # key->rounds
944         movups  ($ivp),$iv
945         movdqu  ($cmac),$inout1
946         movdqa  .Lincrement64(%rip),$increment
947         movdqa  .Lbswap_mask(%rip),$bswap_mask
948
949         movaps  $iv,$inout0
950         mov     $rounds,$rnds_
951         mov     $key,$key_
952         pshufb  $bswap_mask,$iv
953 ___
954         &aesni_generate1("enc",$key,$rounds);
955 $code.=<<___;
956         movups  ($inp),$in0                     # load inp
957         paddq   $increment,$iv
958         lea     16($inp),$inp
959         jmp     .Lccm64_dec_outer
960 .align  16
961 .Lccm64_dec_outer:
962         xorps   $inout0,$in0                    # inp ^= E(iv)
963         movdqa  $iv,$inout0
964         mov     $rnds_,$rounds
965         movups  $in0,($out)                     # save output
966         lea     16($out),$out
967         pshufb  $bswap_mask,$inout0
968
969         sub     \$1,$len
970         jz      .Lccm64_dec_break
971
972         $movkey ($key_),$rndkey0
973         shr     \$1,$rounds
974         $movkey 16($key_),$rndkey1
975         xorps   $rndkey0,$in0
976         lea     32($key_),$key
977         xorps   $rndkey0,$inout0
978         xorps   $in0,$inout1                    # cmac^=out
979         $movkey ($key),$rndkey0
980
981 .Lccm64_dec2_loop:
982         aesenc  $rndkey1,$inout0
983         dec     $rounds
984         aesenc  $rndkey1,$inout1
985         $movkey 16($key),$rndkey1
986         aesenc  $rndkey0,$inout0
987         lea     32($key),$key
988         aesenc  $rndkey0,$inout1
989         $movkey 0($key),$rndkey0
990         jnz     .Lccm64_dec2_loop
991         movups  ($inp),$in0                     # load inp
992         paddq   $increment,$iv
993         aesenc  $rndkey1,$inout0
994         aesenc  $rndkey1,$inout1
995         lea     16($inp),$inp
996         aesenclast      $rndkey0,$inout0
997         aesenclast      $rndkey0,$inout1
998         jmp     .Lccm64_dec_outer
999
1000 .align  16
1001 .Lccm64_dec_break:
1002         #xorps  $in0,$inout1                    # cmac^=out
1003 ___
1004         &aesni_generate1("enc",$key_,$rounds,$inout1,$in0);
1005 $code.=<<___;
1006         movups  $inout1,($cmac)
1007 ___
1008 $code.=<<___ if ($win64);
1009         movaps  (%rsp),%xmm6
1010         movaps  0x10(%rsp),%xmm7
1011         movaps  0x20(%rsp),%xmm8
1012         movaps  0x30(%rsp),%xmm9
1013         lea     0x58(%rsp),%rsp
1014 .Lccm64_dec_ret:
1015 ___
1016 $code.=<<___;
1017         ret
1018 .size   aesni_ccm64_decrypt_blocks,.-aesni_ccm64_decrypt_blocks
1019 ___
1020 }\f
1021 ######################################################################
1022 # void aesni_ctr32_encrypt_blocks (const void *in, void *out,
1023 #                         size_t blocks, const AES_KEY *key,
1024 #                         const char *ivec);
1025 #
1026 # Handles only complete blocks, operates on 32-bit counter and
1027 # does not update *ivec! (see engine/eng_aesni.c for details)
1028 #
1029 {
1030 my $reserved = $win64?0:-0x28;
1031 my ($in0,$in1,$in2,$in3)=map("%xmm$_",(8..11));
1032 my ($iv0,$iv1,$ivec)=("%xmm12","%xmm13","%xmm14");
1033 my $bswap_mask="%xmm15";
1034
1035 $code.=<<___;
1036 .globl  aesni_ctr32_encrypt_blocks
1037 .type   aesni_ctr32_encrypt_blocks,\@function,5
1038 .align  16
1039 aesni_ctr32_encrypt_blocks:
1040 ___
1041 $code.=<<___ if ($win64);
1042         lea     -0xc8(%rsp),%rsp
1043         movaps  %xmm6,0x20(%rsp)
1044         movaps  %xmm7,0x30(%rsp)
1045         movaps  %xmm8,0x40(%rsp)
1046         movaps  %xmm9,0x50(%rsp)
1047         movaps  %xmm10,0x60(%rsp)
1048         movaps  %xmm11,0x70(%rsp)
1049         movaps  %xmm12,0x80(%rsp)
1050         movaps  %xmm13,0x90(%rsp)
1051         movaps  %xmm14,0xa0(%rsp)
1052         movaps  %xmm15,0xb0(%rsp)
1053 .Lctr32_body:
1054 ___
1055 $code.=<<___;
1056         cmp     \$1,$len
1057         je      .Lctr32_one_shortcut
1058
1059         movdqu  ($ivp),$ivec
1060         movdqa  .Lbswap_mask(%rip),$bswap_mask
1061         xor     $rounds,$rounds
1062         pextrd  \$3,$ivec,$rnds_                # pull 32-bit counter
1063         pinsrd  \$3,$rounds,$ivec               # wipe 32-bit counter
1064
1065         mov     240($key),$rounds               # key->rounds
1066         bswap   $rnds_
1067         pxor    $iv0,$iv0                       # vector of 3 32-bit counters
1068         pxor    $iv1,$iv1                       # vector of 3 32-bit counters
1069         pinsrd  \$0,$rnds_,$iv0
1070         lea     3($rnds_),$key_
1071         pinsrd  \$0,$key_,$iv1
1072         inc     $rnds_
1073         pinsrd  \$1,$rnds_,$iv0
1074         inc     $key_
1075         pinsrd  \$1,$key_,$iv1
1076         inc     $rnds_
1077         pinsrd  \$2,$rnds_,$iv0
1078         inc     $key_
1079         pinsrd  \$2,$key_,$iv1
1080         movdqa  $iv0,$reserved(%rsp)
1081         pshufb  $bswap_mask,$iv0
1082         movdqa  $iv1,`$reserved+0x10`(%rsp)
1083         pshufb  $bswap_mask,$iv1
1084
1085         pshufd  \$`3<<6`,$iv0,$inout0           # place counter to upper dword
1086         pshufd  \$`2<<6`,$iv0,$inout1
1087         pshufd  \$`1<<6`,$iv0,$inout2
1088         cmp     \$6,$len
1089         jb      .Lctr32_tail
1090         shr     \$1,$rounds
1091         mov     $key,$key_                      # backup $key
1092         mov     $rounds,$rnds_                  # backup $rounds
1093         sub     \$6,$len
1094         jmp     .Lctr32_loop6
1095
1096 .align  16
1097 .Lctr32_loop6:
1098         pshufd  \$`3<<6`,$iv1,$inout3
1099         por     $ivec,$inout0                   # merge counter-less ivec
1100          $movkey        ($key_),$rndkey0
1101         pshufd  \$`2<<6`,$iv1,$inout4
1102         por     $ivec,$inout1
1103          $movkey        16($key_),$rndkey1
1104         pshufd  \$`1<<6`,$iv1,$inout5
1105         por     $ivec,$inout2
1106         por     $ivec,$inout3
1107          xorps          $rndkey0,$inout0
1108         por     $ivec,$inout4
1109         por     $ivec,$inout5
1110
1111         # inline _aesni_encrypt6 and interleave last rounds
1112         # with own code...
1113
1114         pxor            $rndkey0,$inout1
1115         aesenc          $rndkey1,$inout0
1116         lea             32($key_),$key
1117         pxor            $rndkey0,$inout2
1118         aesenc          $rndkey1,$inout1
1119          movdqa         .Lincrement32(%rip),$iv1
1120         pxor            $rndkey0,$inout3
1121         aesenc          $rndkey1,$inout2
1122          movdqa         $reserved(%rsp),$iv0
1123         pxor            $rndkey0,$inout4
1124         aesenc          $rndkey1,$inout3
1125         pxor            $rndkey0,$inout5
1126         $movkey         ($key),$rndkey0
1127         dec             $rounds
1128         aesenc          $rndkey1,$inout4
1129         aesenc          $rndkey1,$inout5
1130         jmp             .Lctr32_enc_loop6_enter
1131 .align  16
1132 .Lctr32_enc_loop6:
1133         aesenc          $rndkey1,$inout0
1134         aesenc          $rndkey1,$inout1
1135         dec             $rounds
1136         aesenc          $rndkey1,$inout2
1137         aesenc          $rndkey1,$inout3
1138         aesenc          $rndkey1,$inout4
1139         aesenc          $rndkey1,$inout5
1140 .Lctr32_enc_loop6_enter:
1141         $movkey         16($key),$rndkey1
1142         aesenc          $rndkey0,$inout0
1143         aesenc          $rndkey0,$inout1
1144         lea             32($key),$key
1145         aesenc          $rndkey0,$inout2
1146         aesenc          $rndkey0,$inout3
1147         aesenc          $rndkey0,$inout4
1148         aesenc          $rndkey0,$inout5
1149         $movkey         ($key),$rndkey0
1150         jnz             .Lctr32_enc_loop6
1151
1152         aesenc          $rndkey1,$inout0
1153          paddd          $iv1,$iv0               # increment counter vector
1154         aesenc          $rndkey1,$inout1
1155          paddd          `$reserved+0x10`(%rsp),$iv1
1156         aesenc          $rndkey1,$inout2
1157          movdqa         $iv0,$reserved(%rsp)    # save counter vector
1158         aesenc          $rndkey1,$inout3
1159          movdqa         $iv1,`$reserved+0x10`(%rsp)
1160         aesenc          $rndkey1,$inout4
1161          pshufb         $bswap_mask,$iv0        # byte swap
1162         aesenc          $rndkey1,$inout5
1163          pshufb         $bswap_mask,$iv1
1164
1165         aesenclast      $rndkey0,$inout0
1166          movups         ($inp),$in0             # load input
1167         aesenclast      $rndkey0,$inout1
1168          movups         0x10($inp),$in1
1169         aesenclast      $rndkey0,$inout2
1170          movups         0x20($inp),$in2
1171         aesenclast      $rndkey0,$inout3
1172          movups         0x30($inp),$in3
1173         aesenclast      $rndkey0,$inout4
1174          movups         0x40($inp),$rndkey1
1175         aesenclast      $rndkey0,$inout5
1176          movups         0x50($inp),$rndkey0
1177          lea    0x60($inp),$inp
1178
1179         xorps   $inout0,$in0                    # xor
1180          pshufd \$`3<<6`,$iv0,$inout0
1181         xorps   $inout1,$in1
1182          pshufd \$`2<<6`,$iv0,$inout1
1183         movups  $in0,($out)                     # store output
1184         xorps   $inout2,$in2
1185          pshufd \$`1<<6`,$iv0,$inout2
1186         movups  $in1,0x10($out)
1187         xorps   $inout3,$in3
1188         movups  $in2,0x20($out)
1189         xorps   $inout4,$rndkey1
1190         movups  $in3,0x30($out)
1191         xorps   $inout5,$rndkey0
1192         movups  $rndkey1,0x40($out)
1193         movups  $rndkey0,0x50($out)
1194         lea     0x60($out),$out
1195         mov     $rnds_,$rounds
1196         sub     \$6,$len
1197         jnc     .Lctr32_loop6
1198
1199         add     \$6,$len
1200         jz      .Lctr32_done
1201         mov     $key_,$key                      # restore $key
1202         lea     1($rounds,$rounds),$rounds      # restore original value
1203
1204 .Lctr32_tail:
1205         por     $ivec,$inout0
1206         movups  ($inp),$in0
1207         cmp     \$2,$len
1208         jb      .Lctr32_one
1209
1210         por     $ivec,$inout1
1211         movups  0x10($inp),$in1
1212         je      .Lctr32_two
1213
1214         pshufd  \$`3<<6`,$iv1,$inout3
1215         por     $ivec,$inout2
1216         movups  0x20($inp),$in2
1217         cmp     \$4,$len
1218         jb      .Lctr32_three
1219
1220         pshufd  \$`2<<6`,$iv1,$inout4
1221         por     $ivec,$inout3
1222         movups  0x30($inp),$in3
1223         je      .Lctr32_four
1224
1225         por     $ivec,$inout4
1226         xorps   $inout5,$inout5
1227
1228         call    _aesni_encrypt6
1229
1230         movups  0x40($inp),$rndkey1
1231         xorps   $inout0,$in0
1232         xorps   $inout1,$in1
1233         movups  $in0,($out)
1234         xorps   $inout2,$in2
1235         movups  $in1,0x10($out)
1236         xorps   $inout3,$in3
1237         movups  $in2,0x20($out)
1238         xorps   $inout4,$rndkey1
1239         movups  $in3,0x30($out)
1240         movups  $rndkey1,0x40($out)
1241         jmp     .Lctr32_done
1242
1243 .align  16
1244 .Lctr32_one_shortcut:
1245         movups  ($ivp),$inout0
1246         movups  ($inp),$in0
1247         mov     240($key),$rounds               # key->rounds
1248 .Lctr32_one:
1249 ___
1250         &aesni_generate1("enc",$key,$rounds);
1251 $code.=<<___;
1252         xorps   $inout0,$in0
1253         movups  $in0,($out)
1254         jmp     .Lctr32_done
1255
1256 .align  16
1257 .Lctr32_two:
1258         xorps   $inout2,$inout2
1259         call    _aesni_encrypt3
1260         xorps   $inout0,$in0
1261         xorps   $inout1,$in1
1262         movups  $in0,($out)
1263         movups  $in1,0x10($out)
1264         jmp     .Lctr32_done
1265
1266 .align  16
1267 .Lctr32_three:
1268         call    _aesni_encrypt3
1269         xorps   $inout0,$in0
1270         xorps   $inout1,$in1
1271         movups  $in0,($out)
1272         xorps   $inout2,$in2
1273         movups  $in1,0x10($out)
1274         movups  $in2,0x20($out)
1275         jmp     .Lctr32_done
1276
1277 .align  16
1278 .Lctr32_four:
1279         call    _aesni_encrypt4
1280         xorps   $inout0,$in0
1281         xorps   $inout1,$in1
1282         movups  $in0,($out)
1283         xorps   $inout2,$in2
1284         movups  $in1,0x10($out)
1285         xorps   $inout3,$in3
1286         movups  $in2,0x20($out)
1287         movups  $in3,0x30($out)
1288
1289 .Lctr32_done:
1290 ___
1291 $code.=<<___ if ($win64);
1292         movaps  0x20(%rsp),%xmm6
1293         movaps  0x30(%rsp),%xmm7
1294         movaps  0x40(%rsp),%xmm8
1295         movaps  0x50(%rsp),%xmm9
1296         movaps  0x60(%rsp),%xmm10
1297         movaps  0x70(%rsp),%xmm11
1298         movaps  0x80(%rsp),%xmm12
1299         movaps  0x90(%rsp),%xmm13
1300         movaps  0xa0(%rsp),%xmm14
1301         movaps  0xb0(%rsp),%xmm15
1302         lea     0xc8(%rsp),%rsp
1303 .Lctr32_ret:
1304 ___
1305 $code.=<<___;
1306         ret
1307 .size   aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks
1308 ___
1309 }
1310 \f
1311 ######################################################################
1312 # void aesni_xts_[en|de]crypt(const char *inp,char *out,size_t len,
1313 #       const AES_KEY *key1, const AES_KEY *key2
1314 #       const unsigned char iv[16]);
1315 #
1316 {
1317 my @tweak=map("%xmm$_",(10..15));
1318 my ($twmask,$twres,$twtmp)=("%xmm8","%xmm9",@tweak[4]);
1319 my ($key2,$ivp,$len_)=("%r8","%r9","%r9");
1320 my $frame_size = 0x68 + ($win64?160:0);
1321
1322 $code.=<<___;
1323 .globl  aesni_xts_encrypt
1324 .type   aesni_xts_encrypt,\@function,6
1325 .align  16
1326 aesni_xts_encrypt:
1327         lea     -$frame_size(%rsp),%rsp
1328 ___
1329 $code.=<<___ if ($win64);
1330         movaps  %xmm6,0x60(%rsp)
1331         movaps  %xmm7,0x70(%rsp)
1332         movaps  %xmm8,0x80(%rsp)
1333         movaps  %xmm9,0x90(%rsp)
1334         movaps  %xmm10,0xa0(%rsp)
1335         movaps  %xmm11,0xb0(%rsp)
1336         movaps  %xmm12,0xc0(%rsp)
1337         movaps  %xmm13,0xd0(%rsp)
1338         movaps  %xmm14,0xe0(%rsp)
1339         movaps  %xmm15,0xf0(%rsp)
1340 .Lxts_enc_body:
1341 ___
1342 $code.=<<___;
1343         movups  ($ivp),@tweak[5]                # load clear-text tweak
1344         mov     240(%r8),$rounds                # key2->rounds
1345         mov     240($key),$rnds_                # key1->rounds
1346 ___
1347         # generate the tweak
1348         &aesni_generate1("enc",$key2,$rounds,@tweak[5]);
1349 $code.=<<___;
1350         mov     $key,$key_                      # backup $key
1351         mov     $rnds_,$rounds                  # backup $rounds
1352         mov     $len,$len_                      # backup $len
1353         and     \$-16,$len
1354
1355         movdqa  .Lxts_magic(%rip),$twmask
1356         pxor    $twtmp,$twtmp
1357         pcmpgtd @tweak[5],$twtmp                # broadcast upper bits
1358 ___
1359     for ($i=0;$i<4;$i++) {
1360     $code.=<<___;
1361         pshufd  \$0x13,$twtmp,$twres
1362         pxor    $twtmp,$twtmp
1363         movdqa  @tweak[5],@tweak[$i]
1364         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1365         pand    $twmask,$twres                  # isolate carry and residue
1366         pcmpgtd @tweak[5],$twtmp                # broadcat upper bits
1367         pxor    $twres,@tweak[5]
1368 ___
1369     }
1370 $code.=<<___;
1371         sub     \$16*6,$len
1372         jc      .Lxts_enc_short
1373
1374         shr     \$1,$rounds
1375         sub     \$1,$rounds
1376         mov     $rounds,$rnds_
1377         jmp     .Lxts_enc_grandloop
1378
1379 .align  16
1380 .Lxts_enc_grandloop:
1381         pshufd  \$0x13,$twtmp,$twres
1382         movdqa  @tweak[5],@tweak[4]
1383         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1384         movdqu  `16*0`($inp),$inout0            # load input
1385         pand    $twmask,$twres                  # isolate carry and residue
1386         movdqu  `16*1`($inp),$inout1
1387         pxor    $twres,@tweak[5]
1388
1389         movdqu  `16*2`($inp),$inout2
1390         pxor    @tweak[0],$inout0               # input^=tweak
1391         movdqu  `16*3`($inp),$inout3
1392         pxor    @tweak[1],$inout1
1393         movdqu  `16*4`($inp),$inout4
1394         pxor    @tweak[2],$inout2
1395         movdqu  `16*5`($inp),$inout5
1396         lea     `16*6`($inp),$inp
1397         pxor    @tweak[3],$inout3
1398         $movkey         ($key_),$rndkey0
1399         pxor    @tweak[4],$inout4
1400         pxor    @tweak[5],$inout5
1401
1402         # inline _aesni_encrypt6 and interleave first and last rounds
1403         # with own code...
1404         $movkey         16($key_),$rndkey1
1405         pxor            $rndkey0,$inout0
1406         pxor            $rndkey0,$inout1
1407          movdqa @tweak[0],`16*0`(%rsp)          # put aside tweaks
1408         aesenc          $rndkey1,$inout0
1409         lea             32($key_),$key
1410         pxor            $rndkey0,$inout2
1411          movdqa @tweak[1],`16*1`(%rsp)
1412         aesenc          $rndkey1,$inout1
1413         pxor            $rndkey0,$inout3
1414          movdqa @tweak[2],`16*2`(%rsp)
1415         aesenc          $rndkey1,$inout2
1416         pxor            $rndkey0,$inout4
1417          movdqa @tweak[3],`16*3`(%rsp)
1418         aesenc          $rndkey1,$inout3
1419         pxor            $rndkey0,$inout5
1420         $movkey         ($key),$rndkey0
1421         dec             $rounds
1422          movdqa @tweak[4],`16*4`(%rsp)
1423         aesenc          $rndkey1,$inout4
1424          movdqa @tweak[5],`16*5`(%rsp)
1425         aesenc          $rndkey1,$inout5
1426         pxor    $twtmp,$twtmp
1427         pcmpgtd @tweak[5],$twtmp
1428         jmp             .Lxts_enc_loop6_enter
1429
1430 .align  16
1431 .Lxts_enc_loop6:
1432         aesenc          $rndkey1,$inout0
1433         aesenc          $rndkey1,$inout1
1434         dec             $rounds
1435         aesenc          $rndkey1,$inout2
1436         aesenc          $rndkey1,$inout3
1437         aesenc          $rndkey1,$inout4
1438         aesenc          $rndkey1,$inout5
1439 .Lxts_enc_loop6_enter:
1440         $movkey         16($key),$rndkey1
1441         aesenc          $rndkey0,$inout0
1442         aesenc          $rndkey0,$inout1
1443         lea             32($key),$key
1444         aesenc          $rndkey0,$inout2
1445         aesenc          $rndkey0,$inout3
1446         aesenc          $rndkey0,$inout4
1447         aesenc          $rndkey0,$inout5
1448         $movkey         ($key),$rndkey0
1449         jnz             .Lxts_enc_loop6
1450
1451         pshufd  \$0x13,$twtmp,$twres
1452         pxor    $twtmp,$twtmp
1453         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1454          aesenc         $rndkey1,$inout0
1455         pand    $twmask,$twres                  # isolate carry and residue
1456          aesenc         $rndkey1,$inout1
1457         pcmpgtd @tweak[5],$twtmp                # broadcast upper bits
1458          aesenc         $rndkey1,$inout2
1459         pxor    $twres,@tweak[5]
1460          aesenc         $rndkey1,$inout3
1461          aesenc         $rndkey1,$inout4
1462          aesenc         $rndkey1,$inout5
1463          $movkey        16($key),$rndkey1
1464
1465         pshufd  \$0x13,$twtmp,$twres
1466         pxor    $twtmp,$twtmp
1467         movdqa  @tweak[5],@tweak[0]
1468         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1469          aesenc         $rndkey0,$inout0
1470         pand    $twmask,$twres                  # isolate carry and residue
1471          aesenc         $rndkey0,$inout1
1472         pcmpgtd @tweak[5],$twtmp                # broadcat upper bits
1473          aesenc         $rndkey0,$inout2
1474         pxor    $twres,@tweak[5]
1475          aesenc         $rndkey0,$inout3
1476          aesenc         $rndkey0,$inout4
1477          aesenc         $rndkey0,$inout5
1478          $movkey        32($key),$rndkey0
1479
1480         pshufd  \$0x13,$twtmp,$twres
1481         pxor    $twtmp,$twtmp
1482         movdqa  @tweak[5],@tweak[1]
1483         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1484          aesenc         $rndkey1,$inout0
1485         pand    $twmask,$twres                  # isolate carry and residue
1486          aesenc         $rndkey1,$inout1
1487         pcmpgtd @tweak[5],$twtmp                # broadcat upper bits
1488          aesenc         $rndkey1,$inout2
1489         pxor    $twres,@tweak[5]
1490          aesenc         $rndkey1,$inout3
1491          aesenc         $rndkey1,$inout4
1492          aesenc         $rndkey1,$inout5
1493
1494         pshufd  \$0x13,$twtmp,$twres
1495         pxor    $twtmp,$twtmp
1496         movdqa  @tweak[5],@tweak[2]
1497         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1498          aesenclast     $rndkey0,$inout0
1499         pand    $twmask,$twres                  # isolate carry and residue
1500          aesenclast     $rndkey0,$inout1
1501         pcmpgtd @tweak[5],$twtmp                # broadcat upper bits
1502          aesenclast     $rndkey0,$inout2
1503         pxor    $twres,@tweak[5]
1504          aesenclast     $rndkey0,$inout3
1505          aesenclast     $rndkey0,$inout4
1506          aesenclast     $rndkey0,$inout5
1507
1508         pshufd  \$0x13,$twtmp,$twres
1509         pxor    $twtmp,$twtmp
1510         movdqa  @tweak[5],@tweak[3]
1511         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1512          xorps  `16*0`(%rsp),$inout0            # output^=tweak
1513         pand    $twmask,$twres                  # isolate carry and residue
1514          xorps  `16*1`(%rsp),$inout1
1515         pcmpgtd @tweak[5],$twtmp                # broadcat upper bits
1516         pxor    $twres,@tweak[5]
1517
1518         xorps   `16*2`(%rsp),$inout2
1519         movups  $inout0,`16*0`($out)            # write output
1520         xorps   `16*3`(%rsp),$inout3
1521         movups  $inout1,`16*1`($out)
1522         xorps   `16*4`(%rsp),$inout4
1523         movups  $inout2,`16*2`($out)
1524         xorps   `16*5`(%rsp),$inout5
1525         movups  $inout3,`16*3`($out)
1526         mov     $rnds_,$rounds                  # restore $rounds
1527         movups  $inout4,`16*4`($out)
1528         movups  $inout5,`16*5`($out)
1529         lea     `16*6`($out),$out
1530         sub     \$16*6,$len
1531         jnc     .Lxts_enc_grandloop
1532
1533         lea     3($rounds,$rounds),$rounds      # restore original value
1534         mov     $key_,$key                      # restore $key
1535         mov     $rounds,$rnds_                  # backup $rounds
1536
1537 .Lxts_enc_short:
1538         add     \$16*6,$len
1539         jz      .Lxts_enc_done
1540
1541         cmp     \$0x20,$len
1542         jb      .Lxts_enc_one
1543         je      .Lxts_enc_two
1544
1545         cmp     \$0x40,$len
1546         jb      .Lxts_enc_three
1547         je      .Lxts_enc_four
1548
1549         pshufd  \$0x13,$twtmp,$twres
1550         movdqa  @tweak[5],@tweak[4]
1551         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1552          movdqu ($inp),$inout0
1553         pand    $twmask,$twres                  # isolate carry and residue
1554          movdqu 16*1($inp),$inout1
1555         pxor    $twres,@tweak[5]
1556
1557         movdqu  16*2($inp),$inout2
1558         pxor    @tweak[0],$inout0
1559         movdqu  16*3($inp),$inout3
1560         pxor    @tweak[1],$inout1
1561         movdqu  16*4($inp),$inout4
1562         lea     16*5($inp),$inp
1563         pxor    @tweak[2],$inout2
1564         pxor    @tweak[3],$inout3
1565         pxor    @tweak[4],$inout4
1566
1567         call    _aesni_encrypt6
1568
1569         xorps   @tweak[0],$inout0
1570         movdqa  @tweak[5],@tweak[0]
1571         xorps   @tweak[1],$inout1
1572         xorps   @tweak[2],$inout2
1573         movdqu  $inout0,($out)
1574         xorps   @tweak[3],$inout3
1575         movdqu  $inout1,16*1($out)
1576         xorps   @tweak[4],$inout4
1577         movdqu  $inout2,16*2($out)
1578         movdqu  $inout3,16*3($out)
1579         movdqu  $inout4,16*4($out)
1580         lea     16*5($out),$out
1581         jmp     .Lxts_enc_done
1582
1583 .align  16
1584 .Lxts_enc_one:
1585         movups  ($inp),$inout0
1586         lea     16*1($inp),$inp
1587         xorps   @tweak[0],$inout0
1588 ___
1589         &aesni_generate1("enc",$key,$rounds);
1590 $code.=<<___;
1591         xorps   @tweak[0],$inout0
1592         movdqa  @tweak[1],@tweak[0]
1593         movups  $inout0,($out)
1594         lea     16*1($out),$out
1595         jmp     .Lxts_enc_done
1596
1597 .align  16
1598 .Lxts_enc_two:
1599         movups  ($inp),$inout0
1600         movups  16($inp),$inout1
1601         lea     32($inp),$inp
1602         xorps   @tweak[0],$inout0
1603         xorps   @tweak[1],$inout1
1604
1605         call    _aesni_encrypt3
1606
1607         xorps   @tweak[0],$inout0
1608         movdqa  @tweak[2],@tweak[0]
1609         xorps   @tweak[1],$inout1
1610         movups  $inout0,($out)
1611         movups  $inout1,16*1($out)
1612         lea     16*2($out),$out
1613         jmp     .Lxts_enc_done
1614
1615 .align  16
1616 .Lxts_enc_three:
1617         movups  ($inp),$inout0
1618         movups  16*1($inp),$inout1
1619         movups  16*2($inp),$inout2
1620         lea     16*3($inp),$inp
1621         xorps   @tweak[0],$inout0
1622         xorps   @tweak[1],$inout1
1623         xorps   @tweak[2],$inout2
1624
1625         call    _aesni_encrypt3
1626
1627         xorps   @tweak[0],$inout0
1628         movdqa  @tweak[3],@tweak[0]
1629         xorps   @tweak[1],$inout1
1630         xorps   @tweak[2],$inout2
1631         movups  $inout0,($out)
1632         movups  $inout1,16*1($out)
1633         movups  $inout2,16*2($out)
1634         lea     16*3($out),$out
1635         jmp     .Lxts_enc_done
1636
1637 .align  16
1638 .Lxts_enc_four:
1639         movups  ($inp),$inout0
1640         movups  16*1($inp),$inout1
1641         movups  16*2($inp),$inout2
1642         xorps   @tweak[0],$inout0
1643         movups  16*3($inp),$inout3
1644         lea     16*4($inp),$inp
1645         xorps   @tweak[1],$inout1
1646         xorps   @tweak[2],$inout2
1647         xorps   @tweak[3],$inout3
1648
1649         call    _aesni_encrypt4
1650
1651         xorps   @tweak[0],$inout0
1652         movdqa  @tweak[5],@tweak[0]
1653         xorps   @tweak[1],$inout1
1654         xorps   @tweak[2],$inout2
1655         movups  $inout0,($out)
1656         xorps   @tweak[3],$inout3
1657         movups  $inout1,16*1($out)
1658         movups  $inout2,16*2($out)
1659         movups  $inout3,16*3($out)
1660         lea     16*4($out),$out
1661         jmp     .Lxts_enc_done
1662
1663 .align  16
1664 .Lxts_enc_done:
1665         and     \$15,$len_
1666         jz      .Lxts_enc_ret
1667         mov     $len_,$len
1668
1669 .Lxts_enc_steal:
1670         movzb   ($inp),%eax                     # borrow $rounds ...
1671         movzb   -16($out),%ecx                  # ... and $key
1672         lea     1($inp),$inp
1673         mov     %al,-16($out)
1674         mov     %cl,0($out)
1675         lea     1($out),$out
1676         sub     \$1,$len
1677         jnz     .Lxts_enc_steal
1678
1679         sub     $len_,$out                      # rewind $out
1680         mov     $key_,$key                      # restore $key
1681         mov     $rnds_,$rounds                  # restore $rounds
1682
1683         movups  -16($out),$inout0
1684         xorps   @tweak[0],$inout0
1685 ___
1686         &aesni_generate1("enc",$key,$rounds);
1687 $code.=<<___;
1688         xorps   @tweak[0],$inout0
1689         movups  $inout0,-16($out)
1690
1691 .Lxts_enc_ret:
1692 ___
1693 $code.=<<___ if ($win64);
1694         movaps  0x60(%rsp),%xmm6
1695         movaps  0x70(%rsp),%xmm7
1696         movaps  0x80(%rsp),%xmm8
1697         movaps  0x90(%rsp),%xmm9
1698         movaps  0xa0(%rsp),%xmm10
1699         movaps  0xb0(%rsp),%xmm11
1700         movaps  0xc0(%rsp),%xmm12
1701         movaps  0xd0(%rsp),%xmm13
1702         movaps  0xe0(%rsp),%xmm14
1703         movaps  0xf0(%rsp),%xmm15
1704 ___
1705 $code.=<<___;
1706         lea     $frame_size(%rsp),%rsp
1707 .Lxts_enc_epilogue:
1708         ret
1709 .size   aesni_xts_encrypt,.-aesni_xts_encrypt
1710 ___
1711
1712 $code.=<<___;
1713 .globl  aesni_xts_decrypt
1714 .type   aesni_xts_decrypt,\@function,6
1715 .align  16
1716 aesni_xts_decrypt:
1717         lea     -$frame_size(%rsp),%rsp
1718 ___
1719 $code.=<<___ if ($win64);
1720         movaps  %xmm6,0x60(%rsp)
1721         movaps  %xmm7,0x70(%rsp)
1722         movaps  %xmm8,0x80(%rsp)
1723         movaps  %xmm9,0x90(%rsp)
1724         movaps  %xmm10,0xa0(%rsp)
1725         movaps  %xmm11,0xb0(%rsp)
1726         movaps  %xmm12,0xc0(%rsp)
1727         movaps  %xmm13,0xd0(%rsp)
1728         movaps  %xmm14,0xe0(%rsp)
1729         movaps  %xmm15,0xf0(%rsp)
1730 .Lxts_dec_body:
1731 ___
1732 $code.=<<___;
1733         movups  ($ivp),@tweak[5]                # load clear-text tweak
1734         mov     240($key2),$rounds              # key2->rounds
1735         mov     240($key),$rnds_                # key1->rounds
1736 ___
1737         # generate the tweak
1738         &aesni_generate1("enc",$key2,$rounds,@tweak[5]);
1739 $code.=<<___;
1740         xor     %eax,%eax                       # if ($len%16) len-=16;
1741         test    \$15,$len
1742         setnz   %al
1743         shl     \$4,%rax
1744         sub     %rax,$len
1745
1746         mov     $key,$key_                      # backup $key
1747         mov     $rnds_,$rounds                  # backup $rounds
1748         mov     $len,$len_                      # backup $len
1749         and     \$-16,$len
1750
1751         movdqa  .Lxts_magic(%rip),$twmask
1752         pxor    $twtmp,$twtmp
1753         pcmpgtd @tweak[5],$twtmp                # broadcast upper bits
1754 ___
1755     for ($i=0;$i<4;$i++) {
1756     $code.=<<___;
1757         pshufd  \$0x13,$twtmp,$twres
1758         pxor    $twtmp,$twtmp
1759         movdqa  @tweak[5],@tweak[$i]
1760         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1761         pand    $twmask,$twres                  # isolate carry and residue
1762         pcmpgtd @tweak[5],$twtmp                # broadcat upper bits
1763         pxor    $twres,@tweak[5]
1764 ___
1765     }
1766 $code.=<<___;
1767         sub     \$16*6,$len
1768         jc      .Lxts_dec_short
1769
1770         shr     \$1,$rounds
1771         sub     \$1,$rounds
1772         mov     $rounds,$rnds_
1773         jmp     .Lxts_dec_grandloop
1774
1775 .align  16
1776 .Lxts_dec_grandloop:
1777         pshufd  \$0x13,$twtmp,$twres
1778         movdqa  @tweak[5],@tweak[4]
1779         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1780         movdqu  `16*0`($inp),$inout0            # load input
1781         pand    $twmask,$twres                  # isolate carry and residue
1782         movdqu  `16*1`($inp),$inout1
1783         pxor    $twres,@tweak[5]
1784
1785         movdqu  `16*2`($inp),$inout2
1786         pxor    @tweak[0],$inout0               # input^=tweak
1787         movdqu  `16*3`($inp),$inout3
1788         pxor    @tweak[1],$inout1
1789         movdqu  `16*4`($inp),$inout4
1790         pxor    @tweak[2],$inout2
1791         movdqu  `16*5`($inp),$inout5
1792         lea     `16*6`($inp),$inp
1793         pxor    @tweak[3],$inout3
1794         $movkey         ($key_),$rndkey0
1795         pxor    @tweak[4],$inout4
1796         pxor    @tweak[5],$inout5
1797
1798         # inline _aesni_decrypt6 and interleave first and last rounds
1799         # with own code...
1800         $movkey         16($key_),$rndkey1
1801         pxor            $rndkey0,$inout0
1802         pxor            $rndkey0,$inout1
1803          movdqa @tweak[0],`16*0`(%rsp)          # put aside tweaks
1804         aesdec          $rndkey1,$inout0
1805         lea             32($key_),$key
1806         pxor            $rndkey0,$inout2
1807          movdqa @tweak[1],`16*1`(%rsp)
1808         aesdec          $rndkey1,$inout1
1809         pxor            $rndkey0,$inout3
1810          movdqa @tweak[2],`16*2`(%rsp)
1811         aesdec          $rndkey1,$inout2
1812         pxor            $rndkey0,$inout4
1813          movdqa @tweak[3],`16*3`(%rsp)
1814         aesdec          $rndkey1,$inout3
1815         pxor            $rndkey0,$inout5
1816         $movkey         ($key),$rndkey0
1817         dec             $rounds
1818          movdqa @tweak[4],`16*4`(%rsp)
1819         aesdec          $rndkey1,$inout4
1820          movdqa @tweak[5],`16*5`(%rsp)
1821         aesdec          $rndkey1,$inout5
1822         pxor    $twtmp,$twtmp
1823         pcmpgtd @tweak[5],$twtmp
1824         jmp             .Lxts_dec_loop6_enter
1825
1826 .align  16
1827 .Lxts_dec_loop6:
1828         aesdec          $rndkey1,$inout0
1829         aesdec          $rndkey1,$inout1
1830         dec             $rounds
1831         aesdec          $rndkey1,$inout2
1832         aesdec          $rndkey1,$inout3
1833         aesdec          $rndkey1,$inout4
1834         aesdec          $rndkey1,$inout5
1835 .Lxts_dec_loop6_enter:
1836         $movkey         16($key),$rndkey1
1837         aesdec          $rndkey0,$inout0
1838         aesdec          $rndkey0,$inout1
1839         lea             32($key),$key
1840         aesdec          $rndkey0,$inout2
1841         aesdec          $rndkey0,$inout3
1842         aesdec          $rndkey0,$inout4
1843         aesdec          $rndkey0,$inout5
1844         $movkey         ($key),$rndkey0
1845         jnz             .Lxts_dec_loop6
1846
1847         pshufd  \$0x13,$twtmp,$twres
1848         pxor    $twtmp,$twtmp
1849         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1850          aesdec         $rndkey1,$inout0
1851         pand    $twmask,$twres                  # isolate carry and residue
1852          aesdec         $rndkey1,$inout1
1853         pcmpgtd @tweak[5],$twtmp                # broadcast upper bits
1854          aesdec         $rndkey1,$inout2
1855         pxor    $twres,@tweak[5]
1856          aesdec         $rndkey1,$inout3
1857          aesdec         $rndkey1,$inout4
1858          aesdec         $rndkey1,$inout5
1859          $movkey        16($key),$rndkey1
1860
1861         pshufd  \$0x13,$twtmp,$twres
1862         pxor    $twtmp,$twtmp
1863         movdqa  @tweak[5],@tweak[0]
1864         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1865          aesdec         $rndkey0,$inout0
1866         pand    $twmask,$twres                  # isolate carry and residue
1867          aesdec         $rndkey0,$inout1
1868         pcmpgtd @tweak[5],$twtmp                # broadcat upper bits
1869          aesdec         $rndkey0,$inout2
1870         pxor    $twres,@tweak[5]
1871          aesdec         $rndkey0,$inout3
1872          aesdec         $rndkey0,$inout4
1873          aesdec         $rndkey0,$inout5
1874          $movkey        32($key),$rndkey0
1875
1876         pshufd  \$0x13,$twtmp,$twres
1877         pxor    $twtmp,$twtmp
1878         movdqa  @tweak[5],@tweak[1]
1879         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1880          aesdec         $rndkey1,$inout0
1881         pand    $twmask,$twres                  # isolate carry and residue
1882          aesdec         $rndkey1,$inout1
1883         pcmpgtd @tweak[5],$twtmp                # broadcat upper bits
1884          aesdec         $rndkey1,$inout2
1885         pxor    $twres,@tweak[5]
1886          aesdec         $rndkey1,$inout3
1887          aesdec         $rndkey1,$inout4
1888          aesdec         $rndkey1,$inout5
1889
1890         pshufd  \$0x13,$twtmp,$twres
1891         pxor    $twtmp,$twtmp
1892         movdqa  @tweak[5],@tweak[2]
1893         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1894          aesdeclast     $rndkey0,$inout0
1895         pand    $twmask,$twres                  # isolate carry and residue
1896          aesdeclast     $rndkey0,$inout1
1897         pcmpgtd @tweak[5],$twtmp                # broadcat upper bits
1898          aesdeclast     $rndkey0,$inout2
1899         pxor    $twres,@tweak[5]
1900          aesdeclast     $rndkey0,$inout3
1901          aesdeclast     $rndkey0,$inout4
1902          aesdeclast     $rndkey0,$inout5
1903
1904         pshufd  \$0x13,$twtmp,$twres
1905         pxor    $twtmp,$twtmp
1906         movdqa  @tweak[5],@tweak[3]
1907         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1908          xorps  `16*0`(%rsp),$inout0            # output^=tweak
1909         pand    $twmask,$twres                  # isolate carry and residue
1910          xorps  `16*1`(%rsp),$inout1
1911         pcmpgtd @tweak[5],$twtmp                # broadcat upper bits
1912         pxor    $twres,@tweak[5]
1913
1914         xorps   `16*2`(%rsp),$inout2
1915         movups  $inout0,`16*0`($out)            # write output
1916         xorps   `16*3`(%rsp),$inout3
1917         movups  $inout1,`16*1`($out)
1918         xorps   `16*4`(%rsp),$inout4
1919         movups  $inout2,`16*2`($out)
1920         xorps   `16*5`(%rsp),$inout5
1921         movups  $inout3,`16*3`($out)
1922         mov     $rnds_,$rounds                  # restore $rounds
1923         movups  $inout4,`16*4`($out)
1924         movups  $inout5,`16*5`($out)
1925         lea     `16*6`($out),$out
1926         sub     \$16*6,$len
1927         jnc     .Lxts_dec_grandloop
1928
1929         lea     3($rounds,$rounds),$rounds      # restore original value
1930         mov     $key_,$key                      # restore $key
1931         mov     $rounds,$rnds_                  # backup $rounds
1932
1933 .Lxts_dec_short:
1934         add     \$16*6,$len
1935         jz      .Lxts_dec_done
1936
1937         cmp     \$0x20,$len
1938         jb      .Lxts_dec_one
1939         je      .Lxts_dec_two
1940
1941         cmp     \$0x40,$len
1942         jb      .Lxts_dec_three
1943         je      .Lxts_dec_four
1944
1945         pshufd  \$0x13,$twtmp,$twres
1946         movdqa  @tweak[5],@tweak[4]
1947         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1948          movdqu ($inp),$inout0
1949         pand    $twmask,$twres                  # isolate carry and residue
1950          movdqu 16*1($inp),$inout1
1951         pxor    $twres,@tweak[5]
1952
1953         movdqu  16*2($inp),$inout2
1954         pxor    @tweak[0],$inout0
1955         movdqu  16*3($inp),$inout3
1956         pxor    @tweak[1],$inout1
1957         movdqu  16*4($inp),$inout4
1958         lea     16*5($inp),$inp
1959         pxor    @tweak[2],$inout2
1960         pxor    @tweak[3],$inout3
1961         pxor    @tweak[4],$inout4
1962
1963         call    _aesni_decrypt6
1964
1965         xorps   @tweak[0],$inout0
1966         xorps   @tweak[1],$inout1
1967         xorps   @tweak[2],$inout2
1968         movdqu  $inout0,($out)
1969         xorps   @tweak[3],$inout3
1970         movdqu  $inout1,16*1($out)
1971         xorps   @tweak[4],$inout4
1972         movdqu  $inout2,16*2($out)
1973          pxor           $twtmp,$twtmp
1974         movdqu  $inout3,16*3($out)
1975          pcmpgtd        @tweak[5],$twtmp
1976         movdqu  $inout4,16*4($out)
1977         lea     16*5($out),$out
1978          pshufd         \$0x13,$twtmp,@tweak[1] # $twres
1979         and     \$15,$len_
1980         jz      .Lxts_dec_ret
1981
1982         movdqa  @tweak[5],@tweak[0]
1983         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
1984         pand    $twmask,@tweak[1]               # isolate carry and residue
1985         pxor    @tweak[5],@tweak[1]
1986         jmp     .Lxts_dec_done2
1987
1988 .align  16
1989 .Lxts_dec_one:
1990         movups  ($inp),$inout0
1991         lea     16*1($inp),$inp
1992         xorps   @tweak[0],$inout0
1993 ___
1994         &aesni_generate1("dec",$key,$rounds);
1995 $code.=<<___;
1996         xorps   @tweak[0],$inout0
1997         movdqa  @tweak[1],@tweak[0]
1998         movups  $inout0,($out)
1999         movdqa  @tweak[2],@tweak[1]
2000         lea     16*1($out),$out
2001         jmp     .Lxts_dec_done
2002
2003 .align  16
2004 .Lxts_dec_two:
2005         movups  ($inp),$inout0
2006         movups  16($inp),$inout1
2007         lea     32($inp),$inp
2008         xorps   @tweak[0],$inout0
2009         xorps   @tweak[1],$inout1
2010
2011         call    _aesni_decrypt3
2012
2013         xorps   @tweak[0],$inout0
2014         movdqa  @tweak[2],@tweak[0]
2015         xorps   @tweak[1],$inout1
2016         movdqa  @tweak[3],@tweak[1]
2017         movups  $inout0,($out)
2018         movups  $inout1,16*1($out)
2019         lea     16*2($out),$out
2020         jmp     .Lxts_dec_done
2021
2022 .align  16
2023 .Lxts_dec_three:
2024         movups  ($inp),$inout0
2025         movups  16*1($inp),$inout1
2026         movups  16*2($inp),$inout2
2027         lea     16*3($inp),$inp
2028         xorps   @tweak[0],$inout0
2029         xorps   @tweak[1],$inout1
2030         xorps   @tweak[2],$inout2
2031
2032         call    _aesni_decrypt3
2033
2034         xorps   @tweak[0],$inout0
2035         movdqa  @tweak[3],@tweak[0]
2036         xorps   @tweak[1],$inout1
2037         movdqa  @tweak[5],@tweak[1]
2038         xorps   @tweak[2],$inout2
2039         movups  $inout0,($out)
2040         movups  $inout1,16*1($out)
2041         movups  $inout2,16*2($out)
2042         lea     16*3($out),$out
2043         jmp     .Lxts_dec_done
2044
2045 .align  16
2046 .Lxts_dec_four:
2047         pshufd  \$0x13,$twtmp,$twres
2048         movdqa  @tweak[5],@tweak[4]
2049         paddq   @tweak[5],@tweak[5]             # psllq 1,$tweak
2050          movups ($inp),$inout0
2051         pand    $twmask,$twres                  # isolate carry and residue
2052          movups 16*1($inp),$inout1
2053         pxor    $twres,@tweak[5]
2054
2055         movups  16*2($inp),$inout2
2056         xorps   @tweak[0],$inout0
2057         movups  16*3($inp),$inout3
2058         lea     16*4($inp),$inp
2059         xorps   @tweak[1],$inout1
2060         xorps   @tweak[2],$inout2
2061         xorps   @tweak[3],$inout3
2062
2063         call    _aesni_decrypt4
2064
2065         xorps   @tweak[0],$inout0
2066         movdqa  @tweak[4],@tweak[0]
2067         xorps   @tweak[1],$inout1
2068         movdqa  @tweak[5],@tweak[1]
2069         xorps   @tweak[2],$inout2
2070         movups  $inout0,($out)
2071         xorps   @tweak[3],$inout3
2072         movups  $inout1,16*1($out)
2073         movups  $inout2,16*2($out)
2074         movups  $inout3,16*3($out)
2075         lea     16*4($out),$out
2076         jmp     .Lxts_dec_done
2077
2078 .align  16
2079 .Lxts_dec_done:
2080         and     \$15,$len_
2081         jz      .Lxts_dec_ret
2082 .Lxts_dec_done2:
2083         mov     $len_,$len
2084         mov     $key_,$key                      # restore $key
2085         mov     $rnds_,$rounds                  # restore $rounds
2086
2087         movups  ($inp),$inout0
2088         xorps   @tweak[1],$inout0
2089 ___
2090         &aesni_generate1("dec",$key,$rounds);
2091 $code.=<<___;
2092         xorps   @tweak[1],$inout0
2093         movups  $inout0,($out)
2094
2095 .Lxts_dec_steal:
2096         movzb   16($inp),%eax                   # borrow $rounds ...
2097         movzb   ($out),%ecx                     # ... and $key
2098         lea     1($inp),$inp
2099         mov     %al,($out)
2100         mov     %cl,16($out)
2101         lea     1($out),$out
2102         sub     \$1,$len
2103         jnz     .Lxts_dec_steal
2104
2105         sub     $len_,$out                      # rewind $out
2106         mov     $key_,$key                      # restore $key
2107         mov     $rnds_,$rounds                  # restore $rounds
2108
2109         movups  ($out),$inout0
2110         xorps   @tweak[0],$inout0
2111 ___
2112         &aesni_generate1("dec",$key,$rounds);
2113 $code.=<<___;
2114         xorps   @tweak[0],$inout0
2115         movups  $inout0,($out)
2116
2117 .Lxts_dec_ret:
2118 ___
2119 $code.=<<___ if ($win64);
2120         movaps  0x60(%rsp),%xmm6
2121         movaps  0x70(%rsp),%xmm7
2122         movaps  0x80(%rsp),%xmm8
2123         movaps  0x90(%rsp),%xmm9
2124         movaps  0xa0(%rsp),%xmm10
2125         movaps  0xb0(%rsp),%xmm11
2126         movaps  0xc0(%rsp),%xmm12
2127         movaps  0xd0(%rsp),%xmm13
2128         movaps  0xe0(%rsp),%xmm14
2129         movaps  0xf0(%rsp),%xmm15
2130 ___
2131 $code.=<<___;
2132         lea     $frame_size(%rsp),%rsp
2133 .Lxts_dec_epilogue:
2134         ret
2135 .size   aesni_xts_decrypt,.-aesni_xts_decrypt
2136 ___
2137 } }}
2138 \f
2139 ########################################################################
2140 # void $PREFIX_cbc_encrypt (const void *inp, void *out,
2141 #                           size_t length, const AES_KEY *key,
2142 #                           unsigned char *ivp,const int enc);
2143 {
2144 my $reserved = $win64?0x40:-0x18;       # used in decrypt
2145 $code.=<<___;
2146 .globl  ${PREFIX}_cbc_encrypt
2147 .type   ${PREFIX}_cbc_encrypt,\@function,6
2148 .align  16
2149 ${PREFIX}_cbc_encrypt:
2150         test    $len,$len               # check length
2151         jz      .Lcbc_ret
2152
2153         mov     240($key),$rnds_        # key->rounds
2154         mov     $key,$key_              # backup $key
2155         test    %r9d,%r9d               # 6th argument
2156         jz      .Lcbc_decrypt
2157 #--------------------------- CBC ENCRYPT ------------------------------#
2158         movups  ($ivp),$inout0          # load iv as initial state
2159         mov     $rnds_,$rounds
2160         cmp     \$16,$len
2161         jb      .Lcbc_enc_tail
2162         sub     \$16,$len
2163         jmp     .Lcbc_enc_loop
2164 .align  16
2165 .Lcbc_enc_loop:
2166         movups  ($inp),$inout1          # load input
2167         lea     16($inp),$inp
2168         #xorps  $inout1,$inout0
2169 ___
2170         &aesni_generate1("enc",$key,$rounds,$inout0,$inout1);
2171 $code.=<<___;
2172         mov     $rnds_,$rounds          # restore $rounds
2173         mov     $key_,$key              # restore $key
2174         movups  $inout0,0($out)         # store output
2175         lea     16($out),$out
2176         sub     \$16,$len
2177         jnc     .Lcbc_enc_loop
2178         add     \$16,$len
2179         jnz     .Lcbc_enc_tail
2180         movups  $inout0,($ivp)
2181         jmp     .Lcbc_ret
2182
2183 .Lcbc_enc_tail:
2184         mov     $len,%rcx       # zaps $key
2185         xchg    $inp,$out       # $inp is %rsi and $out is %rdi now
2186         .long   0x9066A4F3      # rep movsb
2187         mov     \$16,%ecx       # zero tail
2188         sub     $len,%rcx
2189         xor     %eax,%eax
2190         .long   0x9066AAF3      # rep stosb
2191         lea     -16(%rdi),%rdi  # rewind $out by 1 block
2192         mov     $rnds_,$rounds  # restore $rounds
2193         mov     %rdi,%rsi       # $inp and $out are the same
2194         mov     $key_,$key      # restore $key
2195         xor     $len,$len       # len=16
2196         jmp     .Lcbc_enc_loop  # one more spin
2197 \f#--------------------------- CBC DECRYPT ------------------------------#
2198 .align  16
2199 .Lcbc_decrypt:
2200 ___
2201 $code.=<<___ if ($win64);
2202         lea     -0x58(%rsp),%rsp
2203         movaps  %xmm6,(%rsp)
2204         movaps  %xmm7,0x10(%rsp)
2205         movaps  %xmm8,0x20(%rsp)
2206         movaps  %xmm9,0x30(%rsp)
2207 .Lcbc_decrypt_body:
2208 ___
2209 $code.=<<___;
2210         movups  ($ivp),$iv
2211         mov     $rnds_,$rounds
2212         cmp     \$0x70,$len
2213         jbe     .Lcbc_dec_tail
2214         shr     \$1,$rnds_
2215         sub     \$0x70,$len
2216         mov     $rnds_,$rounds
2217         movaps  $iv,$reserved(%rsp)
2218         jmp     .Lcbc_dec_loop8_enter
2219 .align  16
2220 .Lcbc_dec_loop8:
2221         movaps  $rndkey0,$reserved(%rsp)        # save IV
2222         movups  $inout7,($out)
2223         lea     0x10($out),$out
2224 .Lcbc_dec_loop8_enter:
2225         $movkey         ($key),$rndkey0
2226         movups  ($inp),$inout0                  # load input
2227         movups  0x10($inp),$inout1
2228         $movkey         16($key),$rndkey1
2229
2230         lea             32($key),$key
2231         movdqu  0x20($inp),$inout2
2232         xorps           $rndkey0,$inout0
2233         movdqu  0x30($inp),$inout3
2234         xorps           $rndkey0,$inout1
2235         movdqu  0x40($inp),$inout4
2236         aesdec          $rndkey1,$inout0
2237         pxor            $rndkey0,$inout2
2238         movdqu  0x50($inp),$inout5
2239         aesdec          $rndkey1,$inout1
2240         pxor            $rndkey0,$inout3
2241         movdqu  0x60($inp),$inout6
2242         aesdec          $rndkey1,$inout2
2243         pxor            $rndkey0,$inout4
2244         movdqu  0x70($inp),$inout7
2245         aesdec          $rndkey1,$inout3
2246         pxor            $rndkey0,$inout5
2247         dec             $rounds
2248         aesdec          $rndkey1,$inout4
2249         pxor            $rndkey0,$inout6
2250         aesdec          $rndkey1,$inout5
2251         pxor            $rndkey0,$inout7
2252         $movkey         ($key),$rndkey0
2253         aesdec          $rndkey1,$inout6
2254         aesdec          $rndkey1,$inout7
2255         $movkey         16($key),$rndkey1
2256
2257         call            .Ldec_loop8_enter
2258
2259         movups  ($inp),$rndkey1         # re-load input
2260         movups  0x10($inp),$rndkey0
2261         xorps   $reserved(%rsp),$inout0 # ^= IV
2262         xorps   $rndkey1,$inout1
2263         movups  0x20($inp),$rndkey1
2264         xorps   $rndkey0,$inout2
2265         movups  0x30($inp),$rndkey0
2266         xorps   $rndkey1,$inout3
2267         movups  0x40($inp),$rndkey1
2268         xorps   $rndkey0,$inout4
2269         movups  0x50($inp),$rndkey0
2270         xorps   $rndkey1,$inout5
2271         movups  0x60($inp),$rndkey1
2272         xorps   $rndkey0,$inout6
2273         movups  0x70($inp),$rndkey0     # IV
2274         xorps   $rndkey1,$inout7
2275         movups  $inout0,($out)
2276         movups  $inout1,0x10($out)
2277         movups  $inout2,0x20($out)
2278         movups  $inout3,0x30($out)
2279         mov     $rnds_,$rounds          # restore $rounds
2280         movups  $inout4,0x40($out)
2281         mov     $key_,$key              # restore $key
2282         movups  $inout5,0x50($out)
2283         lea     0x80($inp),$inp
2284         movups  $inout6,0x60($out)
2285         lea     0x70($out),$out
2286         sub     \$0x80,$len
2287         ja      .Lcbc_dec_loop8
2288
2289         movaps  $inout7,$inout0
2290         movaps  $rndkey0,$iv
2291         add     \$0x70,$len
2292         jle     .Lcbc_dec_tail_collected
2293         movups  $inout0,($out)
2294         lea     1($rnds_,$rnds_),$rounds
2295         lea     0x10($out),$out
2296 .Lcbc_dec_tail:
2297         movups  ($inp),$inout0
2298         movaps  $inout0,$in0
2299         cmp     \$0x10,$len
2300         jbe     .Lcbc_dec_one
2301
2302         movups  0x10($inp),$inout1
2303         movaps  $inout1,$in1
2304         cmp     \$0x20,$len
2305         jbe     .Lcbc_dec_two
2306
2307         movups  0x20($inp),$inout2
2308         movaps  $inout2,$in2
2309         cmp     \$0x30,$len
2310         jbe     .Lcbc_dec_three
2311
2312         movups  0x30($inp),$inout3
2313         cmp     \$0x40,$len
2314         jbe     .Lcbc_dec_four
2315
2316         movups  0x40($inp),$inout4
2317         cmp     \$0x50,$len
2318         jbe     .Lcbc_dec_five
2319
2320         movups  0x50($inp),$inout5
2321         cmp     \$0x60,$len
2322         jbe     .Lcbc_dec_six
2323
2324         movups  0x60($inp),$inout6
2325         movaps  $iv,$reserved(%rsp)     # save IV
2326         call    _aesni_decrypt8
2327         movups  ($inp),$rndkey1
2328         movups  0x10($inp),$rndkey0
2329         xorps   $reserved(%rsp),$inout0 # ^= IV
2330         xorps   $rndkey1,$inout1
2331         movups  0x20($inp),$rndkey1
2332         xorps   $rndkey0,$inout2
2333         movups  0x30($inp),$rndkey0
2334         xorps   $rndkey1,$inout3
2335         movups  0x40($inp),$rndkey1
2336         xorps   $rndkey0,$inout4
2337         movups  0x50($inp),$rndkey0
2338         xorps   $rndkey1,$inout5
2339         movups  0x60($inp),$iv          # IV
2340         xorps   $rndkey0,$inout6
2341         movups  $inout0,($out)
2342         movups  $inout1,0x10($out)
2343         movups  $inout2,0x20($out)
2344         movups  $inout3,0x30($out)
2345         movups  $inout4,0x40($out)
2346         movups  $inout5,0x50($out)
2347         lea     0x60($out),$out
2348         movaps  $inout6,$inout0
2349         sub     \$0x70,$len
2350         jmp     .Lcbc_dec_tail_collected
2351 .align  16
2352 .Lcbc_dec_one:
2353 ___
2354         &aesni_generate1("dec",$key,$rounds);
2355 $code.=<<___;
2356         xorps   $iv,$inout0
2357         movaps  $in0,$iv
2358         sub     \$0x10,$len
2359         jmp     .Lcbc_dec_tail_collected
2360 .align  16
2361 .Lcbc_dec_two:
2362         xorps   $inout2,$inout2
2363         call    _aesni_decrypt3
2364         xorps   $iv,$inout0
2365         xorps   $in0,$inout1
2366         movups  $inout0,($out)
2367         movaps  $in1,$iv
2368         movaps  $inout1,$inout0
2369         lea     0x10($out),$out
2370         sub     \$0x20,$len
2371         jmp     .Lcbc_dec_tail_collected
2372 .align  16
2373 .Lcbc_dec_three:
2374         call    _aesni_decrypt3
2375         xorps   $iv,$inout0
2376         xorps   $in0,$inout1
2377         movups  $inout0,($out)
2378         xorps   $in1,$inout2
2379         movups  $inout1,0x10($out)
2380         movaps  $in2,$iv
2381         movaps  $inout2,$inout0
2382         lea     0x20($out),$out
2383         sub     \$0x30,$len
2384         jmp     .Lcbc_dec_tail_collected
2385 .align  16
2386 .Lcbc_dec_four:
2387         call    _aesni_decrypt4
2388         xorps   $iv,$inout0
2389         movups  0x30($inp),$iv
2390         xorps   $in0,$inout1
2391         movups  $inout0,($out)
2392         xorps   $in1,$inout2
2393         movups  $inout1,0x10($out)
2394         xorps   $in2,$inout3
2395         movups  $inout2,0x20($out)
2396         movaps  $inout3,$inout0
2397         lea     0x30($out),$out
2398         sub     \$0x40,$len
2399         jmp     .Lcbc_dec_tail_collected
2400 .align  16
2401 .Lcbc_dec_five:
2402         xorps   $inout5,$inout5
2403         call    _aesni_decrypt6
2404         movups  0x10($inp),$rndkey1
2405         movups  0x20($inp),$rndkey0
2406         xorps   $iv,$inout0
2407         xorps   $in0,$inout1
2408         xorps   $rndkey1,$inout2
2409         movups  0x30($inp),$rndkey1
2410         xorps   $rndkey0,$inout3
2411         movups  0x40($inp),$iv
2412         xorps   $rndkey1,$inout4
2413         movups  $inout0,($out)
2414         movups  $inout1,0x10($out)
2415         movups  $inout2,0x20($out)
2416         movups  $inout3,0x30($out)
2417         lea     0x40($out),$out
2418         movaps  $inout4,$inout0
2419         sub     \$0x50,$len
2420         jmp     .Lcbc_dec_tail_collected
2421 .align  16
2422 .Lcbc_dec_six:
2423         call    _aesni_decrypt6
2424         movups  0x10($inp),$rndkey1
2425         movups  0x20($inp),$rndkey0
2426         xorps   $iv,$inout0
2427         xorps   $in0,$inout1
2428         xorps   $rndkey1,$inout2
2429         movups  0x30($inp),$rndkey1
2430         xorps   $rndkey0,$inout3
2431         movups  0x40($inp),$rndkey0
2432         xorps   $rndkey1,$inout4
2433         movups  0x50($inp),$iv
2434         xorps   $rndkey0,$inout5
2435         movups  $inout0,($out)
2436         movups  $inout1,0x10($out)
2437         movups  $inout2,0x20($out)
2438         movups  $inout3,0x30($out)
2439         movups  $inout4,0x40($out)
2440         lea     0x50($out),$out
2441         movaps  $inout5,$inout0
2442         sub     \$0x60,$len
2443         jmp     .Lcbc_dec_tail_collected
2444 .align  16
2445 .Lcbc_dec_tail_collected:
2446         and     \$15,$len
2447         movups  $iv,($ivp)
2448         jnz     .Lcbc_dec_tail_partial
2449         movups  $inout0,($out)
2450         jmp     .Lcbc_dec_ret
2451 .align  16
2452 .Lcbc_dec_tail_partial:
2453         movaps  $inout0,$reserved(%rsp)
2454         mov     \$16,%rcx
2455         mov     $out,%rdi
2456         sub     $len,%rcx
2457         lea     $reserved(%rsp),%rsi
2458         .long   0x9066A4F3      # rep movsb
2459
2460 .Lcbc_dec_ret:
2461 ___
2462 $code.=<<___ if ($win64);
2463         movaps  (%rsp),%xmm6
2464         movaps  0x10(%rsp),%xmm7
2465         movaps  0x20(%rsp),%xmm8
2466         movaps  0x30(%rsp),%xmm9
2467         lea     0x58(%rsp),%rsp
2468 ___
2469 $code.=<<___;
2470 .Lcbc_ret:
2471         ret
2472 .size   ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt
2473 ___
2474\f
2475 # int $PREFIX_set_[en|de]crypt_key (const unsigned char *userKey,
2476 #                               int bits, AES_KEY *key)
2477 { my ($inp,$bits,$key) = @_4args;
2478   $bits =~ s/%r/%e/;
2479
2480 $code.=<<___;
2481 .globl  ${PREFIX}_set_decrypt_key
2482 .type   ${PREFIX}_set_decrypt_key,\@abi-omnipotent
2483 .align  16
2484 ${PREFIX}_set_decrypt_key:
2485         .byte   0x48,0x83,0xEC,0x08     # sub rsp,8
2486         call    __aesni_set_encrypt_key
2487         shl     \$4,$bits               # rounds-1 after _aesni_set_encrypt_key
2488         test    %eax,%eax
2489         jnz     .Ldec_key_ret
2490         lea     16($key,$bits),$inp     # points at the end of key schedule
2491
2492         $movkey ($key),%xmm0            # just swap
2493         $movkey ($inp),%xmm1
2494         $movkey %xmm0,($inp)
2495         $movkey %xmm1,($key)
2496         lea     16($key),$key
2497         lea     -16($inp),$inp
2498
2499 .Ldec_key_inverse:
2500         $movkey ($key),%xmm0            # swap and inverse
2501         $movkey ($inp),%xmm1
2502         aesimc  %xmm0,%xmm0
2503         aesimc  %xmm1,%xmm1
2504         lea     16($key),$key
2505         lea     -16($inp),$inp
2506         $movkey %xmm0,16($inp)
2507         $movkey %xmm1,-16($key)
2508         cmp     $key,$inp
2509         ja      .Ldec_key_inverse
2510
2511         $movkey ($key),%xmm0            # inverse middle
2512         aesimc  %xmm0,%xmm0
2513         $movkey %xmm0,($inp)
2514 .Ldec_key_ret:
2515         add     \$8,%rsp
2516         ret
2517 .LSEH_end_set_decrypt_key:
2518 .size   ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key
2519 ___
2520 \f
2521 # This is based on submission by
2522 #
2523 #       Huang Ying <ying.huang@intel.com>
2524 #       Vinodh Gopal <vinodh.gopal@intel.com>
2525 #       Kahraman Akdemir
2526 #
2527 # Agressively optimized in respect to aeskeygenassist's critical path
2528 # and is contained in %xmm0-5 to meet Win64 ABI requirement.
2529 #
2530 $code.=<<___;
2531 .globl  ${PREFIX}_set_encrypt_key
2532 .type   ${PREFIX}_set_encrypt_key,\@abi-omnipotent
2533 .align  16
2534 ${PREFIX}_set_encrypt_key:
2535 __aesni_set_encrypt_key:
2536         .byte   0x48,0x83,0xEC,0x08     # sub rsp,8
2537         mov     \$-1,%rax
2538         test    $inp,$inp
2539         jz      .Lenc_key_ret
2540         test    $key,$key
2541         jz      .Lenc_key_ret
2542
2543         movups  ($inp),%xmm0            # pull first 128 bits of *userKey
2544         xorps   %xmm4,%xmm4             # low dword of xmm4 is assumed 0
2545         lea     16($key),%rax
2546         cmp     \$256,$bits
2547         je      .L14rounds
2548         cmp     \$192,$bits
2549         je      .L12rounds
2550         cmp     \$128,$bits
2551         jne     .Lbad_keybits
2552
2553 .L10rounds:
2554         mov     \$9,$bits                       # 10 rounds for 128-bit key
2555         $movkey %xmm0,($key)                    # round 0
2556         aeskeygenassist \$0x1,%xmm0,%xmm1       # round 1
2557         call            .Lkey_expansion_128_cold
2558         aeskeygenassist \$0x2,%xmm0,%xmm1       # round 2
2559         call            .Lkey_expansion_128
2560         aeskeygenassist \$0x4,%xmm0,%xmm1       # round 3
2561         call            .Lkey_expansion_128
2562         aeskeygenassist \$0x8,%xmm0,%xmm1       # round 4
2563         call            .Lkey_expansion_128
2564         aeskeygenassist \$0x10,%xmm0,%xmm1      # round 5
2565         call            .Lkey_expansion_128
2566         aeskeygenassist \$0x20,%xmm0,%xmm1      # round 6
2567         call            .Lkey_expansion_128
2568         aeskeygenassist \$0x40,%xmm0,%xmm1      # round 7
2569         call            .Lkey_expansion_128
2570         aeskeygenassist \$0x80,%xmm0,%xmm1      # round 8
2571         call            .Lkey_expansion_128
2572         aeskeygenassist \$0x1b,%xmm0,%xmm1      # round 9
2573         call            .Lkey_expansion_128
2574         aeskeygenassist \$0x36,%xmm0,%xmm1      # round 10
2575         call            .Lkey_expansion_128
2576         $movkey %xmm0,(%rax)
2577         mov     $bits,80(%rax)  # 240(%rdx)
2578         xor     %eax,%eax
2579         jmp     .Lenc_key_ret
2580
2581 .align  16
2582 .L12rounds:
2583         movq    16($inp),%xmm2                  # remaining 1/3 of *userKey
2584         mov     \$11,$bits                      # 12 rounds for 192
2585         $movkey %xmm0,($key)                    # round 0
2586         aeskeygenassist \$0x1,%xmm2,%xmm1       # round 1,2
2587         call            .Lkey_expansion_192a_cold
2588         aeskeygenassist \$0x2,%xmm2,%xmm1       # round 2,3
2589         call            .Lkey_expansion_192b
2590         aeskeygenassist \$0x4,%xmm2,%xmm1       # round 4,5
2591         call            .Lkey_expansion_192a
2592         aeskeygenassist \$0x8,%xmm2,%xmm1       # round 5,6
2593         call            .Lkey_expansion_192b
2594         aeskeygenassist \$0x10,%xmm2,%xmm1      # round 7,8
2595         call            .Lkey_expansion_192a
2596         aeskeygenassist \$0x20,%xmm2,%xmm1      # round 8,9
2597         call            .Lkey_expansion_192b
2598         aeskeygenassist \$0x40,%xmm2,%xmm1      # round 10,11
2599         call            .Lkey_expansion_192a
2600         aeskeygenassist \$0x80,%xmm2,%xmm1      # round 11,12
2601         call            .Lkey_expansion_192b
2602         $movkey %xmm0,(%rax)
2603         mov     $bits,48(%rax)  # 240(%rdx)
2604         xor     %rax, %rax
2605         jmp     .Lenc_key_ret
2606
2607 .align  16
2608 .L14rounds:
2609         movups  16($inp),%xmm2                  # remaning half of *userKey
2610         mov     \$13,$bits                      # 14 rounds for 256
2611         lea     16(%rax),%rax
2612         $movkey %xmm0,($key)                    # round 0
2613         $movkey %xmm2,16($key)                  # round 1
2614         aeskeygenassist \$0x1,%xmm2,%xmm1       # round 2
2615         call            .Lkey_expansion_256a_cold
2616         aeskeygenassist \$0x1,%xmm0,%xmm1       # round 3
2617         call            .Lkey_expansion_256b
2618         aeskeygenassist \$0x2,%xmm2,%xmm1       # round 4
2619         call            .Lkey_expansion_256a
2620         aeskeygenassist \$0x2,%xmm0,%xmm1       # round 5
2621         call            .Lkey_expansion_256b
2622         aeskeygenassist \$0x4,%xmm2,%xmm1       # round 6
2623         call            .Lkey_expansion_256a
2624         aeskeygenassist \$0x4,%xmm0,%xmm1       # round 7
2625         call            .Lkey_expansion_256b
2626         aeskeygenassist \$0x8,%xmm2,%xmm1       # round 8
2627         call            .Lkey_expansion_256a
2628         aeskeygenassist \$0x8,%xmm0,%xmm1       # round 9
2629         call            .Lkey_expansion_256b
2630         aeskeygenassist \$0x10,%xmm2,%xmm1      # round 10
2631         call            .Lkey_expansion_256a
2632         aeskeygenassist \$0x10,%xmm0,%xmm1      # round 11
2633         call            .Lkey_expansion_256b
2634         aeskeygenassist \$0x20,%xmm2,%xmm1      # round 12
2635         call            .Lkey_expansion_256a
2636         aeskeygenassist \$0x20,%xmm0,%xmm1      # round 13
2637         call            .Lkey_expansion_256b
2638         aeskeygenassist \$0x40,%xmm2,%xmm1      # round 14
2639         call            .Lkey_expansion_256a
2640         $movkey %xmm0,(%rax)
2641         mov     $bits,16(%rax)  # 240(%rdx)
2642         xor     %rax,%rax
2643         jmp     .Lenc_key_ret
2644
2645 .align  16
2646 .Lbad_keybits:
2647         mov     \$-2,%rax
2648 .Lenc_key_ret:
2649         add     \$8,%rsp
2650         ret
2651 .LSEH_end_set_encrypt_key:
2652 \f
2653 .align  16
2654 .Lkey_expansion_128:
2655         $movkey %xmm0,(%rax)
2656         lea     16(%rax),%rax
2657 .Lkey_expansion_128_cold:
2658         shufps  \$0b00010000,%xmm0,%xmm4
2659         xorps   %xmm4, %xmm0
2660         shufps  \$0b10001100,%xmm0,%xmm4
2661         xorps   %xmm4, %xmm0
2662         shufps  \$0b11111111,%xmm1,%xmm1        # critical path
2663         xorps   %xmm1,%xmm0
2664         ret
2665
2666 .align 16
2667 .Lkey_expansion_192a:
2668         $movkey %xmm0,(%rax)
2669         lea     16(%rax),%rax
2670 .Lkey_expansion_192a_cold:
2671         movaps  %xmm2, %xmm5
2672 .Lkey_expansion_192b_warm:
2673         shufps  \$0b00010000,%xmm0,%xmm4
2674         movdqa  %xmm2,%xmm3
2675         xorps   %xmm4,%xmm0
2676         shufps  \$0b10001100,%xmm0,%xmm4
2677         pslldq  \$4,%xmm3
2678         xorps   %xmm4,%xmm0
2679         pshufd  \$0b01010101,%xmm1,%xmm1        # critical path
2680         pxor    %xmm3,%xmm2
2681         pxor    %xmm1,%xmm0
2682         pshufd  \$0b11111111,%xmm0,%xmm3
2683         pxor    %xmm3,%xmm2
2684         ret
2685
2686 .align 16
2687 .Lkey_expansion_192b:
2688         movaps  %xmm0,%xmm3
2689         shufps  \$0b01000100,%xmm0,%xmm5
2690         $movkey %xmm5,(%rax)
2691         shufps  \$0b01001110,%xmm2,%xmm3
2692         $movkey %xmm3,16(%rax)
2693         lea     32(%rax),%rax
2694         jmp     .Lkey_expansion_192b_warm
2695
2696 .align  16
2697 .Lkey_expansion_256a:
2698         $movkey %xmm2,(%rax)
2699         lea     16(%rax),%rax
2700 .Lkey_expansion_256a_cold:
2701         shufps  \$0b00010000,%xmm0,%xmm4
2702         xorps   %xmm4,%xmm0
2703         shufps  \$0b10001100,%xmm0,%xmm4
2704         xorps   %xmm4,%xmm0
2705         shufps  \$0b11111111,%xmm1,%xmm1        # critical path
2706         xorps   %xmm1,%xmm0
2707         ret
2708
2709 .align 16
2710 .Lkey_expansion_256b:
2711         $movkey %xmm0,(%rax)
2712         lea     16(%rax),%rax
2713
2714         shufps  \$0b00010000,%xmm2,%xmm4
2715         xorps   %xmm4,%xmm2
2716         shufps  \$0b10001100,%xmm2,%xmm4
2717         xorps   %xmm4,%xmm2
2718         shufps  \$0b10101010,%xmm1,%xmm1        # critical path
2719         xorps   %xmm1,%xmm2
2720         ret
2721 .size   ${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key
2722 .size   __aesni_set_encrypt_key,.-__aesni_set_encrypt_key
2723 ___
2724 }
2725 \f
2726 $code.=<<___;
2727 .align  64
2728 .Lbswap_mask:
2729         .byte   15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
2730 .Lincrement32:
2731         .long   6,6,6,0
2732 .Lincrement64:
2733         .long   1,0,0,0
2734 .Lxts_magic:
2735         .long   0x87,0,1,0
2736
2737 .asciz  "AES for Intel AES-NI, CRYPTOGAMS by <appro\@openssl.org>"
2738 .align  64
2739 ___
2740
2741 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
2742 #               CONTEXT *context,DISPATCHER_CONTEXT *disp)
2743 if ($win64) {
2744 $rec="%rcx";
2745 $frame="%rdx";
2746 $context="%r8";
2747 $disp="%r9";
2748
2749 $code.=<<___;
2750 .extern __imp_RtlVirtualUnwind
2751 ___
2752 $code.=<<___ if ($PREFIX eq "aesni");
2753 .type   ecb_ccm64_se_handler,\@abi-omnipotent
2754 .align  16
2755 ecb_ccm64_se_handler:
2756         push    %rsi
2757         push    %rdi
2758         push    %rbx
2759         push    %rbp
2760         push    %r12
2761         push    %r13
2762         push    %r14
2763         push    %r15
2764         pushfq
2765         sub     \$64,%rsp
2766
2767         mov     120($context),%rax      # pull context->Rax
2768         mov     248($context),%rbx      # pull context->Rip
2769
2770         mov     8($disp),%rsi           # disp->ImageBase
2771         mov     56($disp),%r11          # disp->HandlerData
2772
2773         mov     0(%r11),%r10d           # HandlerData[0]
2774         lea     (%rsi,%r10),%r10        # prologue label
2775         cmp     %r10,%rbx               # context->Rip<prologue label
2776         jb      .Lcommon_seh_tail
2777
2778         mov     152($context),%rax      # pull context->Rsp
2779
2780         mov     4(%r11),%r10d           # HandlerData[1]
2781         lea     (%rsi,%r10),%r10        # epilogue label
2782         cmp     %r10,%rbx               # context->Rip>=epilogue label
2783         jae     .Lcommon_seh_tail
2784
2785         lea     0(%rax),%rsi            # %xmm save area
2786         lea     512($context),%rdi      # &context.Xmm6
2787         mov     \$8,%ecx                # 4*sizeof(%xmm0)/sizeof(%rax)
2788         .long   0xa548f3fc              # cld; rep movsq
2789         lea     0x58(%rax),%rax         # adjust stack pointer
2790
2791         jmp     .Lcommon_seh_tail
2792 .size   ecb_ccm64_se_handler,.-ecb_ccm64_se_handler
2793
2794 .type   ctr32_se_handler,\@abi-omnipotent
2795 .align  16
2796 ctr32_se_handler:
2797         push    %rsi
2798         push    %rdi
2799         push    %rbx
2800         push    %rbp
2801         push    %r12
2802         push    %r13
2803         push    %r14
2804         push    %r15
2805         pushfq
2806         sub     \$64,%rsp
2807
2808         mov     120($context),%rax      # pull context->Rax
2809         mov     248($context),%rbx      # pull context->Rip
2810
2811         lea     .Lctr32_body(%rip),%r10
2812         cmp     %r10,%rbx               # context->Rip<"prologue" label
2813         jb      .Lcommon_seh_tail
2814
2815         mov     152($context),%rax      # pull context->Rsp
2816
2817         lea     .Lctr32_ret(%rip),%r10
2818         cmp     %r10,%rbx
2819         jae     .Lcommon_seh_tail
2820
2821         lea     0x20(%rax),%rsi         # %xmm save area
2822         lea     512($context),%rdi      # &context.Xmm6
2823         mov     \$20,%ecx               # 10*sizeof(%xmm0)/sizeof(%rax)
2824         .long   0xa548f3fc              # cld; rep movsq
2825         lea     0xc8(%rax),%rax         # adjust stack pointer
2826
2827         jmp     .Lcommon_seh_tail
2828 .size   ctr32_se_handler,.-ctr32_se_handler
2829
2830 .type   xts_se_handler,\@abi-omnipotent
2831 .align  16
2832 xts_se_handler:
2833         push    %rsi
2834         push    %rdi
2835         push    %rbx
2836         push    %rbp
2837         push    %r12
2838         push    %r13
2839         push    %r14
2840         push    %r15
2841         pushfq
2842         sub     \$64,%rsp
2843
2844         mov     120($context),%rax      # pull context->Rax
2845         mov     248($context),%rbx      # pull context->Rip
2846
2847         mov     8($disp),%rsi           # disp->ImageBase
2848         mov     56($disp),%r11          # disp->HandlerData
2849
2850         mov     0(%r11),%r10d           # HandlerData[0]
2851         lea     (%rsi,%r10),%r10        # prologue lable
2852         cmp     %r10,%rbx               # context->Rip<prologue label
2853         jb      .Lcommon_seh_tail
2854
2855         mov     152($context),%rax      # pull context->Rsp
2856
2857         mov     4(%r11),%r10d           # HandlerData[1]
2858         lea     (%rsi,%r10),%r10        # epilogue label
2859         cmp     %r10,%rbx               # context->Rip>=epilogue label
2860         jae     .Lcommon_seh_tail
2861
2862         lea     0x60(%rax),%rsi         # %xmm save area
2863         lea     512($context),%rdi      # & context.Xmm6
2864         mov     \$20,%ecx               # 10*sizeof(%xmm0)/sizeof(%rax)
2865         .long   0xa548f3fc              # cld; rep movsq
2866         lea     0x68+160(%rax),%rax     # adjust stack pointer
2867
2868         jmp     .Lcommon_seh_tail
2869 .size   xts_se_handler,.-xts_se_handler
2870 ___
2871 $code.=<<___;
2872 .type   cbc_se_handler,\@abi-omnipotent
2873 .align  16
2874 cbc_se_handler:
2875         push    %rsi
2876         push    %rdi
2877         push    %rbx
2878         push    %rbp
2879         push    %r12
2880         push    %r13
2881         push    %r14
2882         push    %r15
2883         pushfq
2884         sub     \$64,%rsp
2885
2886         mov     152($context),%rax      # pull context->Rsp
2887         mov     248($context),%rbx      # pull context->Rip
2888
2889         lea     .Lcbc_decrypt(%rip),%r10
2890         cmp     %r10,%rbx               # context->Rip<"prologue" label
2891         jb      .Lcommon_seh_tail
2892
2893         lea     .Lcbc_decrypt_body(%rip),%r10
2894         cmp     %r10,%rbx               # context->Rip<cbc_decrypt_body
2895         jb      .Lrestore_cbc_rax
2896
2897         lea     .Lcbc_ret(%rip),%r10
2898         cmp     %r10,%rbx               # context->Rip>="epilogue" label
2899         jae     .Lcommon_seh_tail
2900
2901         lea     0(%rax),%rsi            # top of stack
2902         lea     512($context),%rdi      # &context.Xmm6
2903         mov     \$8,%ecx                # 4*sizeof(%xmm0)/sizeof(%rax)
2904         .long   0xa548f3fc              # cld; rep movsq
2905         lea     0x58(%rax),%rax         # adjust stack pointer
2906         jmp     .Lcommon_seh_tail
2907
2908 .Lrestore_cbc_rax:
2909         mov     120($context),%rax
2910
2911 .Lcommon_seh_tail:
2912         mov     8(%rax),%rdi
2913         mov     16(%rax),%rsi
2914         mov     %rax,152($context)      # restore context->Rsp
2915         mov     %rsi,168($context)      # restore context->Rsi
2916         mov     %rdi,176($context)      # restore context->Rdi
2917
2918         mov     40($disp),%rdi          # disp->ContextRecord
2919         mov     $context,%rsi           # context
2920         mov     \$154,%ecx              # sizeof(CONTEXT)
2921         .long   0xa548f3fc              # cld; rep movsq
2922
2923         mov     $disp,%rsi
2924         xor     %rcx,%rcx               # arg1, UNW_FLAG_NHANDLER
2925         mov     8(%rsi),%rdx            # arg2, disp->ImageBase
2926         mov     0(%rsi),%r8             # arg3, disp->ControlPc
2927         mov     16(%rsi),%r9            # arg4, disp->FunctionEntry
2928         mov     40(%rsi),%r10           # disp->ContextRecord
2929         lea     56(%rsi),%r11           # &disp->HandlerData
2930         lea     24(%rsi),%r12           # &disp->EstablisherFrame
2931         mov     %r10,32(%rsp)           # arg5
2932         mov     %r11,40(%rsp)           # arg6
2933         mov     %r12,48(%rsp)           # arg7
2934         mov     %rcx,56(%rsp)           # arg8, (NULL)
2935         call    *__imp_RtlVirtualUnwind(%rip)
2936
2937         mov     \$1,%eax                # ExceptionContinueSearch
2938         add     \$64,%rsp
2939         popfq
2940         pop     %r15
2941         pop     %r14
2942         pop     %r13
2943         pop     %r12
2944         pop     %rbp
2945         pop     %rbx
2946         pop     %rdi
2947         pop     %rsi
2948         ret
2949 .size   cbc_se_handler,.-cbc_se_handler
2950
2951 .section        .pdata
2952 .align  4
2953 ___
2954 $code.=<<___ if ($PREFIX eq "aesni");
2955         .rva    .LSEH_begin_aesni_ecb_encrypt
2956         .rva    .LSEH_end_aesni_ecb_encrypt
2957         .rva    .LSEH_info_ecb
2958
2959         .rva    .LSEH_begin_aesni_ccm64_encrypt_blocks
2960         .rva    .LSEH_end_aesni_ccm64_encrypt_blocks
2961         .rva    .LSEH_info_ccm64_enc
2962
2963         .rva    .LSEH_begin_aesni_ccm64_decrypt_blocks
2964         .rva    .LSEH_end_aesni_ccm64_decrypt_blocks
2965         .rva    .LSEH_info_ccm64_dec
2966
2967         .rva    .LSEH_begin_aesni_ctr32_encrypt_blocks
2968         .rva    .LSEH_end_aesni_ctr32_encrypt_blocks
2969         .rva    .LSEH_info_ctr32
2970
2971         .rva    .LSEH_begin_aesni_xts_encrypt
2972         .rva    .LSEH_end_aesni_xts_encrypt
2973         .rva    .LSEH_info_xts_enc
2974
2975         .rva    .LSEH_begin_aesni_xts_decrypt
2976         .rva    .LSEH_end_aesni_xts_decrypt
2977         .rva    .LSEH_info_xts_dec
2978 ___
2979 $code.=<<___;
2980         .rva    .LSEH_begin_${PREFIX}_cbc_encrypt
2981         .rva    .LSEH_end_${PREFIX}_cbc_encrypt
2982         .rva    .LSEH_info_cbc
2983
2984         .rva    ${PREFIX}_set_decrypt_key
2985         .rva    .LSEH_end_set_decrypt_key
2986         .rva    .LSEH_info_key
2987
2988         .rva    ${PREFIX}_set_encrypt_key
2989         .rva    .LSEH_end_set_encrypt_key
2990         .rva    .LSEH_info_key
2991 .section        .xdata
2992 .align  8
2993 ___
2994 $code.=<<___ if ($PREFIX eq "aesni");
2995 .LSEH_info_ecb:
2996         .byte   9,0,0,0
2997         .rva    ecb_ccm64_se_handler
2998         .rva    .Lecb_enc_body,.Lecb_enc_ret            # HandlerData[]
2999 .LSEH_info_ccm64_enc:
3000         .byte   9,0,0,0
3001         .rva    ecb_ccm64_se_handler
3002         .rva    .Lccm64_enc_body,.Lccm64_enc_ret        # HandlerData[]
3003 .LSEH_info_ccm64_dec:
3004         .byte   9,0,0,0
3005         .rva    ecb_ccm64_se_handler
3006         .rva    .Lccm64_dec_body,.Lccm64_dec_ret        # HandlerData[]
3007 .LSEH_info_ctr32:
3008         .byte   9,0,0,0
3009         .rva    ctr32_se_handler
3010 .LSEH_info_xts_enc:
3011         .byte   9,0,0,0
3012         .rva    xts_se_handler
3013         .rva    .Lxts_enc_body,.Lxts_enc_epilogue       # HandlerData[]
3014 .LSEH_info_xts_dec:
3015         .byte   9,0,0,0
3016         .rva    xts_se_handler
3017         .rva    .Lxts_dec_body,.Lxts_dec_epilogue       # HandlerData[]
3018 ___
3019 $code.=<<___;
3020 .LSEH_info_cbc:
3021         .byte   9,0,0,0
3022         .rva    cbc_se_handler
3023 .LSEH_info_key:
3024         .byte   0x01,0x04,0x01,0x00
3025         .byte   0x04,0x02,0x00,0x00     # sub rsp,8
3026 ___
3027 }
3028
3029 sub rex {
3030   local *opcode=shift;
3031   my ($dst,$src)=@_;
3032   my $rex=0;
3033
3034     $rex|=0x04                  if($dst>=8);
3035     $rex|=0x01                  if($src>=8);
3036     push @opcode,$rex|0x40      if($rex);
3037 }
3038
3039 sub aesni {
3040   my $line=shift;
3041   my @opcode=(0x66);
3042
3043     if ($line=~/(aeskeygenassist)\s+\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
3044         rex(\@opcode,$4,$3);
3045         push @opcode,0x0f,0x3a,0xdf;
3046         push @opcode,0xc0|($3&7)|(($4&7)<<3);   # ModR/M
3047         my $c=$2;
3048         push @opcode,$c=~/^0/?oct($c):$c;
3049         return ".byte\t".join(',',@opcode);
3050     }
3051     elsif ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) {
3052         my %opcodelet = (
3053                 "aesimc" => 0xdb,
3054                 "aesenc" => 0xdc,       "aesenclast" => 0xdd,
3055                 "aesdec" => 0xde,       "aesdeclast" => 0xdf
3056         );
3057         return undef if (!defined($opcodelet{$1}));
3058         rex(\@opcode,$3,$2);
3059         push @opcode,0x0f,0x38,$opcodelet{$1};
3060         push @opcode,0xc0|($2&7)|(($3&7)<<3);   # ModR/M
3061         return ".byte\t".join(',',@opcode);
3062     }
3063     return $line;
3064 }
3065
3066 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
3067 $code =~ s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/gem;
3068
3069 print $code;
3070
3071 close STDOUT;