x86_64 assembly pack: Win64 SEH face-lift.
[openssl.git] / crypto / aes / asm / bsaes-x86_64.pl
1 #! /usr/bin/env perl
2 # Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the OpenSSL license (the "License").  You may not use
5 # this file except in compliance with the License.  You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
8
9
10 ###################################################################
11 ### AES-128 [originally in CTR mode]                            ###
12 ### bitsliced implementation for Intel Core 2 processors        ###
13 ### requires support of SSE extensions up to SSSE3              ###
14 ### Author: Emilia Käsper and Peter Schwabe                    ###
15 ### Date: 2009-03-19                                            ###
16 ### Public domain                                               ###
17 ###                                                             ###
18 ### See http://homes.esat.kuleuven.be/~ekasper/#software for    ###
19 ### further information.                                        ###
20 ###################################################################
21 #
22 # September 2011.
23 #
24 # Started as transliteration to "perlasm" the original code has
25 # undergone following changes:
26 #
27 # - code was made position-independent;
28 # - rounds were folded into a loop resulting in >5x size reduction
29 #   from 12.5KB to 2.2KB;
30 # - above was possibile thanks to mixcolumns() modification that
31 #   allowed to feed its output back to aesenc[last], this was
32 #   achieved at cost of two additional inter-registers moves;
33 # - some instruction reordering and interleaving;
34 # - this module doesn't implement key setup subroutine, instead it
35 #   relies on conversion of "conventional" key schedule as returned
36 #   by AES_set_encrypt_key (see discussion below);
37 # - first and last round keys are treated differently, which allowed
38 #   to skip one shiftrows(), reduce bit-sliced key schedule and
39 #   speed-up conversion by 22%;
40 # - support for 192- and 256-bit keys was added;
41 #
42 # Resulting performance in CPU cycles spent to encrypt one byte out
43 # of 4096-byte buffer with 128-bit key is:
44 #
45 #               Emilia's        this(*)         difference
46 #
47 # Core 2        9.30            8.69            +7%
48 # Nehalem(**)   7.63            6.88            +11%
49 # Atom          17.1            16.4            +4%
50 # Silvermont    -               12.9
51 # Goldmont      -               8.85
52 #
53 # (*)   Comparison is not completely fair, because "this" is ECB,
54 #       i.e. no extra processing such as counter values calculation
55 #       and xor-ing input as in Emilia's CTR implementation is
56 #       performed. However, the CTR calculations stand for not more
57 #       than 1% of total time, so comparison is *rather* fair.
58 #
59 # (**)  Results were collected on Westmere, which is considered to
60 #       be equivalent to Nehalem for this code.
61 #
62 # As for key schedule conversion subroutine. Interface to OpenSSL
63 # relies on per-invocation on-the-fly conversion. This naturally
64 # has impact on performance, especially for short inputs. Conversion
65 # time in CPU cycles and its ratio to CPU cycles spent in 8x block
66 # function is:
67 #
68 #               conversion      conversion/8x block
69 # Core 2        240             0.22
70 # Nehalem       180             0.20
71 # Atom          430             0.20
72 #
73 # The ratio values mean that 128-byte blocks will be processed
74 # 16-18% slower, 256-byte blocks - 9-10%, 384-byte blocks - 6-7%,
75 # etc. Then keep in mind that input sizes not divisible by 128 are
76 # *effectively* slower, especially shortest ones, e.g. consecutive
77 # 144-byte blocks are processed 44% slower than one would expect,
78 # 272 - 29%, 400 - 22%, etc. Yet, despite all these "shortcomings"
79 # it's still faster than ["hyper-threading-safe" code path in]
80 # aes-x86_64.pl on all lengths above 64 bytes...
81 #
82 # October 2011.
83 #
84 # Add decryption procedure. Performance in CPU cycles spent to decrypt
85 # one byte out of 4096-byte buffer with 128-bit key is:
86 #
87 # Core 2        9.98
88 # Nehalem       7.80
89 # Atom          17.9
90 # Silvermont    14.0
91 # Goldmont      10.2
92 #
93 # November 2011.
94 #
95 # Add bsaes_xts_[en|de]crypt. Less-than-80-bytes-block performance is
96 # suboptimal, but XTS is meant to be used with larger blocks...
97 #
98 #                                               <appro@openssl.org>
99
100 $flavour = shift;
101 $output  = shift;
102 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
103
104 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
105
106 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
107 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
108 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
109 die "can't locate x86_64-xlate.pl";
110
111 open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
112 *STDOUT=*OUT;
113
114 my ($inp,$out,$len,$key,$ivp)=("%rdi","%rsi","%rdx","%rcx");
115 my @XMM=map("%xmm$_",(15,0..14));       # best on Atom, +10% over (0..15)
116 my $ecb=0;      # suppress unreferenced ECB subroutines, spare some space...
117
118 {
119 my ($key,$rounds,$const)=("%rax","%r10d","%r11");
120
121 sub Sbox {
122 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
123 # output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb
124 my @b=@_[0..7];
125 my @t=@_[8..11];
126 my @s=@_[12..15];
127         &InBasisChange  (@b);
128         &Inv_GF256      (@b[6,5,0,3,7,1,4,2],@t,@s);
129         &OutBasisChange (@b[7,1,4,2,6,5,0,3]);
130 }
131
132 sub InBasisChange {
133 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
134 # output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
135 my @b=@_[0..7];
136 $code.=<<___;
137         pxor    @b[6], @b[5]
138         pxor    @b[1], @b[2]
139         pxor    @b[0], @b[3]
140         pxor    @b[2], @b[6]
141         pxor    @b[0], @b[5]
142
143         pxor    @b[3], @b[6]
144         pxor    @b[7], @b[3]
145         pxor    @b[5], @b[7]
146         pxor    @b[4], @b[3]
147         pxor    @b[5], @b[4]
148         pxor    @b[1], @b[3]
149
150         pxor    @b[7], @b[2]
151         pxor    @b[5], @b[1]
152 ___
153 }
154
155 sub OutBasisChange {
156 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
157 # output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb
158 my @b=@_[0..7];
159 $code.=<<___;
160         pxor    @b[6], @b[0]
161         pxor    @b[4], @b[1]
162         pxor    @b[0], @b[2]
163         pxor    @b[6], @b[4]
164         pxor    @b[1], @b[6]
165
166         pxor    @b[5], @b[1]
167         pxor    @b[3], @b[5]
168         pxor    @b[7], @b[3]
169         pxor    @b[5], @b[7]
170         pxor    @b[5], @b[2]
171
172         pxor    @b[7], @b[4]
173 ___
174 }
175
176 sub InvSbox {
177 # input in lsb  > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
178 # output in lsb > [b0, b1, b6, b4, b2, b7, b3, b5] < msb
179 my @b=@_[0..7];
180 my @t=@_[8..11];
181 my @s=@_[12..15];
182         &InvInBasisChange       (@b);
183         &Inv_GF256              (@b[5,1,2,6,3,7,0,4],@t,@s);
184         &InvOutBasisChange      (@b[3,7,0,4,5,1,2,6]);
185 }
186
187 sub InvInBasisChange {          # OutBasisChange in reverse
188 my @b=@_[5,1,2,6,3,7,0,4];
189 $code.=<<___
190         pxor    @b[7], @b[4]
191
192         pxor    @b[5], @b[7]
193         pxor    @b[5], @b[2]
194         pxor    @b[7], @b[3]
195         pxor    @b[3], @b[5]
196         pxor    @b[5], @b[1]
197
198         pxor    @b[1], @b[6]
199         pxor    @b[0], @b[2]
200         pxor    @b[6], @b[4]
201         pxor    @b[6], @b[0]
202         pxor    @b[4], @b[1]
203 ___
204 }
205
206 sub InvOutBasisChange {         # InBasisChange in reverse
207 my @b=@_[2,5,7,3,6,1,0,4];
208 $code.=<<___;
209         pxor    @b[5], @b[1]
210         pxor    @b[7], @b[2]
211
212         pxor    @b[1], @b[3]
213         pxor    @b[5], @b[4]
214         pxor    @b[5], @b[7]
215         pxor    @b[4], @b[3]
216          pxor   @b[0], @b[5]
217         pxor    @b[7], @b[3]
218          pxor   @b[2], @b[6]
219          pxor   @b[1], @b[2]
220         pxor    @b[3], @b[6]
221
222         pxor    @b[0], @b[3]
223         pxor    @b[6], @b[5]
224 ___
225 }
226
227 sub Mul_GF4 {
228 #;*************************************************************
229 #;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) *
230 #;*************************************************************
231 my ($x0,$x1,$y0,$y1,$t0)=@_;
232 $code.=<<___;
233         movdqa  $y0, $t0
234         pxor    $y1, $t0
235         pand    $x0, $t0
236         pxor    $x1, $x0
237         pand    $y0, $x1
238         pand    $y1, $x0
239         pxor    $x1, $x0
240         pxor    $t0, $x1
241 ___
242 }
243
244 sub Mul_GF4_N {                         # not used, see next subroutine
245 # multiply and scale by N
246 my ($x0,$x1,$y0,$y1,$t0)=@_;
247 $code.=<<___;
248         movdqa  $y0, $t0
249         pxor    $y1, $t0
250         pand    $x0, $t0
251         pxor    $x1, $x0
252         pand    $y0, $x1
253         pand    $y1, $x0
254         pxor    $x0, $x1
255         pxor    $t0, $x0
256 ___
257 }
258
259 sub Mul_GF4_N_GF4 {
260 # interleaved Mul_GF4_N and Mul_GF4
261 my ($x0,$x1,$y0,$y1,$t0,
262     $x2,$x3,$y2,$y3,$t1)=@_;
263 $code.=<<___;
264         movdqa  $y0, $t0
265          movdqa $y2, $t1
266         pxor    $y1, $t0
267          pxor   $y3, $t1
268         pand    $x0, $t0
269          pand   $x2, $t1
270         pxor    $x1, $x0
271          pxor   $x3, $x2
272         pand    $y0, $x1
273          pand   $y2, $x3
274         pand    $y1, $x0
275          pand   $y3, $x2
276         pxor    $x0, $x1
277          pxor   $x3, $x2
278         pxor    $t0, $x0
279          pxor   $t1, $x3
280 ___
281 }
282 sub Mul_GF16_2 {
283 my @x=@_[0..7];
284 my @y=@_[8..11];
285 my @t=@_[12..15];
286 $code.=<<___;
287         movdqa  @x[0], @t[0]
288         movdqa  @x[1], @t[1]
289 ___
290         &Mul_GF4        (@x[0], @x[1], @y[0], @y[1], @t[2]);
291 $code.=<<___;
292         pxor    @x[2], @t[0]
293         pxor    @x[3], @t[1]
294         pxor    @y[2], @y[0]
295         pxor    @y[3], @y[1]
296 ___
297         Mul_GF4_N_GF4   (@t[0], @t[1], @y[0], @y[1], @t[3],
298                          @x[2], @x[3], @y[2], @y[3], @t[2]);
299 $code.=<<___;
300         pxor    @t[0], @x[0]
301         pxor    @t[0], @x[2]
302         pxor    @t[1], @x[1]
303         pxor    @t[1], @x[3]
304
305         movdqa  @x[4], @t[0]
306         movdqa  @x[5], @t[1]
307         pxor    @x[6], @t[0]
308         pxor    @x[7], @t[1]
309 ___
310         &Mul_GF4_N_GF4  (@t[0], @t[1], @y[0], @y[1], @t[3],
311                          @x[6], @x[7], @y[2], @y[3], @t[2]);
312 $code.=<<___;
313         pxor    @y[2], @y[0]
314         pxor    @y[3], @y[1]
315 ___
316         &Mul_GF4        (@x[4], @x[5], @y[0], @y[1], @t[3]);
317 $code.=<<___;
318         pxor    @t[0], @x[4]
319         pxor    @t[0], @x[6]
320         pxor    @t[1], @x[5]
321         pxor    @t[1], @x[7]
322 ___
323 }
324 sub Inv_GF256 {
325 #;********************************************************************
326 #;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144)       *
327 #;********************************************************************
328 my @x=@_[0..7];
329 my @t=@_[8..11];
330 my @s=@_[12..15];
331 # direct optimizations from hardware
332 $code.=<<___;
333         movdqa  @x[4], @t[3]
334         movdqa  @x[5], @t[2]
335         movdqa  @x[1], @t[1]
336         movdqa  @x[7], @s[1]
337         movdqa  @x[0], @s[0]
338
339         pxor    @x[6], @t[3]
340         pxor    @x[7], @t[2]
341         pxor    @x[3], @t[1]
342          movdqa @t[3], @s[2]
343         pxor    @x[6], @s[1]
344          movdqa @t[2], @t[0]
345         pxor    @x[2], @s[0]
346          movdqa @t[3], @s[3]
347
348         por     @t[1], @t[2]
349         por     @s[0], @t[3]
350         pxor    @t[0], @s[3]
351         pand    @s[0], @s[2]
352         pxor    @t[1], @s[0]
353         pand    @t[1], @t[0]
354         pand    @s[0], @s[3]
355         movdqa  @x[3], @s[0]
356         pxor    @x[2], @s[0]
357         pand    @s[0], @s[1]
358         pxor    @s[1], @t[3]
359         pxor    @s[1], @t[2]
360         movdqa  @x[4], @s[1]
361         movdqa  @x[1], @s[0]
362         pxor    @x[5], @s[1]
363         pxor    @x[0], @s[0]
364         movdqa  @s[1], @t[1]
365         pand    @s[0], @s[1]
366         por     @s[0], @t[1]
367         pxor    @s[1], @t[0]
368         pxor    @s[3], @t[3]
369         pxor    @s[2], @t[2]
370         pxor    @s[3], @t[1]
371         movdqa  @x[7], @s[0]
372         pxor    @s[2], @t[0]
373         movdqa  @x[6], @s[1]
374         pxor    @s[2], @t[1]
375         movdqa  @x[5], @s[2]
376         pand    @x[3], @s[0]
377         movdqa  @x[4], @s[3]
378         pand    @x[2], @s[1]
379         pand    @x[1], @s[2]
380         por     @x[0], @s[3]
381         pxor    @s[0], @t[3]
382         pxor    @s[1], @t[2]
383         pxor    @s[2], @t[1]
384         pxor    @s[3], @t[0]
385
386         #Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
387
388         # new smaller inversion
389
390         movdqa  @t[3], @s[0]
391         pand    @t[1], @t[3]
392         pxor    @t[2], @s[0]
393
394         movdqa  @t[0], @s[2]
395         movdqa  @s[0], @s[3]
396         pxor    @t[3], @s[2]
397         pand    @s[2], @s[3]
398
399         movdqa  @t[1], @s[1]
400         pxor    @t[2], @s[3]
401         pxor    @t[0], @s[1]
402
403         pxor    @t[2], @t[3]
404
405         pand    @t[3], @s[1]
406
407         movdqa  @s[2], @t[2]
408         pxor    @t[0], @s[1]
409
410         pxor    @s[1], @t[2]
411         pxor    @s[1], @t[1]
412
413         pand    @t[0], @t[2]
414
415         pxor    @t[2], @s[2]
416         pxor    @t[2], @t[1]
417
418         pand    @s[3], @s[2]
419
420         pxor    @s[0], @s[2]
421 ___
422 # output in s3, s2, s1, t1
423
424 # Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3
425
426 # Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3
427         &Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]);
428
429 ### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb
430 }
431
432 # AES linear components
433
434 sub ShiftRows {
435 my @x=@_[0..7];
436 my $mask=pop;
437 $code.=<<___;
438         pxor    0x00($key),@x[0]
439         pxor    0x10($key),@x[1]
440         pxor    0x20($key),@x[2]
441         pxor    0x30($key),@x[3]
442         pshufb  $mask,@x[0]
443         pshufb  $mask,@x[1]
444         pxor    0x40($key),@x[4]
445         pxor    0x50($key),@x[5]
446         pshufb  $mask,@x[2]
447         pshufb  $mask,@x[3]
448         pxor    0x60($key),@x[6]
449         pxor    0x70($key),@x[7]
450         pshufb  $mask,@x[4]
451         pshufb  $mask,@x[5]
452         pshufb  $mask,@x[6]
453         pshufb  $mask,@x[7]
454         lea     0x80($key),$key
455 ___
456 }
457
458 sub MixColumns {
459 # modified to emit output in order suitable for feeding back to aesenc[last]
460 my @x=@_[0..7];
461 my @t=@_[8..15];
462 my $inv=@_[16]; # optional
463 $code.=<<___;
464         pshufd  \$0x93, @x[0], @t[0]    # x0 <<< 32
465         pshufd  \$0x93, @x[1], @t[1]
466          pxor   @t[0], @x[0]            # x0 ^ (x0 <<< 32)
467         pshufd  \$0x93, @x[2], @t[2]
468          pxor   @t[1], @x[1]
469         pshufd  \$0x93, @x[3], @t[3]
470          pxor   @t[2], @x[2]
471         pshufd  \$0x93, @x[4], @t[4]
472          pxor   @t[3], @x[3]
473         pshufd  \$0x93, @x[5], @t[5]
474          pxor   @t[4], @x[4]
475         pshufd  \$0x93, @x[6], @t[6]
476          pxor   @t[5], @x[5]
477         pshufd  \$0x93, @x[7], @t[7]
478          pxor   @t[6], @x[6]
479          pxor   @t[7], @x[7]
480
481         pxor    @x[0], @t[1]
482         pxor    @x[7], @t[0]
483         pxor    @x[7], @t[1]
484          pshufd \$0x4E, @x[0], @x[0]    # (x0 ^ (x0 <<< 32)) <<< 64)
485         pxor    @x[1], @t[2]
486          pshufd \$0x4E, @x[1], @x[1]
487         pxor    @x[4], @t[5]
488          pxor   @t[0], @x[0]
489         pxor    @x[5], @t[6]
490          pxor   @t[1], @x[1]
491         pxor    @x[3], @t[4]
492          pshufd \$0x4E, @x[4], @t[0]
493         pxor    @x[6], @t[7]
494          pshufd \$0x4E, @x[5], @t[1]
495         pxor    @x[2], @t[3]
496          pshufd \$0x4E, @x[3], @x[4]
497         pxor    @x[7], @t[3]
498          pshufd \$0x4E, @x[7], @x[5]
499         pxor    @x[7], @t[4]
500          pshufd \$0x4E, @x[6], @x[3]
501         pxor    @t[4], @t[0]
502          pshufd \$0x4E, @x[2], @x[6]
503         pxor    @t[5], @t[1]
504 ___
505 $code.=<<___ if (!$inv);
506         pxor    @t[3], @x[4]
507         pxor    @t[7], @x[5]
508         pxor    @t[6], @x[3]
509          movdqa @t[0], @x[2]
510         pxor    @t[2], @x[6]
511          movdqa @t[1], @x[7]
512 ___
513 $code.=<<___ if ($inv);
514         pxor    @x[4], @t[3]
515         pxor    @t[7], @x[5]
516         pxor    @x[3], @t[6]
517          movdqa @t[0], @x[3]
518         pxor    @t[2], @x[6]
519          movdqa @t[6], @x[2]
520          movdqa @t[1], @x[7]
521          movdqa @x[6], @x[4]
522          movdqa @t[3], @x[6]
523 ___
524 }
525
526 sub InvMixColumns_orig {
527 my @x=@_[0..7];
528 my @t=@_[8..15];
529
530 $code.=<<___;
531         # multiplication by 0x0e
532         pshufd  \$0x93, @x[7], @t[7]
533         movdqa  @x[2], @t[2]
534         pxor    @x[5], @x[7]            # 7 5
535         pxor    @x[5], @x[2]            # 2 5
536         pshufd  \$0x93, @x[0], @t[0]
537         movdqa  @x[5], @t[5]
538         pxor    @x[0], @x[5]            # 5 0           [1]
539         pxor    @x[1], @x[0]            # 0 1
540         pshufd  \$0x93, @x[1], @t[1]
541         pxor    @x[2], @x[1]            # 1 25
542         pxor    @x[6], @x[0]            # 01 6          [2]
543         pxor    @x[3], @x[1]            # 125 3         [4]
544         pshufd  \$0x93, @x[3], @t[3]
545         pxor    @x[0], @x[2]            # 25 016        [3]
546         pxor    @x[7], @x[3]            # 3 75
547         pxor    @x[6], @x[7]            # 75 6          [0]
548         pshufd  \$0x93, @x[6], @t[6]
549         movdqa  @x[4], @t[4]
550         pxor    @x[4], @x[6]            # 6 4
551         pxor    @x[3], @x[4]            # 4 375         [6]
552         pxor    @x[7], @x[3]            # 375 756=36
553         pxor    @t[5], @x[6]            # 64 5          [7]
554         pxor    @t[2], @x[3]            # 36 2
555         pxor    @t[4], @x[3]            # 362 4         [5]
556         pshufd  \$0x93, @t[5], @t[5]
557 ___
558                                         my @y = @x[7,5,0,2,1,3,4,6];
559 $code.=<<___;
560         # multiplication by 0x0b
561         pxor    @y[0], @y[1]
562         pxor    @t[0], @y[0]
563         pxor    @t[1], @y[1]
564         pshufd  \$0x93, @t[2], @t[2]
565         pxor    @t[5], @y[0]
566         pxor    @t[6], @y[1]
567         pxor    @t[7], @y[0]
568         pshufd  \$0x93, @t[4], @t[4]
569         pxor    @t[6], @t[7]            # clobber t[7]
570         pxor    @y[0], @y[1]
571
572         pxor    @t[0], @y[3]
573         pshufd  \$0x93, @t[0], @t[0]
574         pxor    @t[1], @y[2]
575         pxor    @t[1], @y[4]
576         pxor    @t[2], @y[2]
577         pshufd  \$0x93, @t[1], @t[1]
578         pxor    @t[2], @y[3]
579         pxor    @t[2], @y[5]
580         pxor    @t[7], @y[2]
581         pshufd  \$0x93, @t[2], @t[2]
582         pxor    @t[3], @y[3]
583         pxor    @t[3], @y[6]
584         pxor    @t[3], @y[4]
585         pshufd  \$0x93, @t[3], @t[3]
586         pxor    @t[4], @y[7]
587         pxor    @t[4], @y[5]
588         pxor    @t[7], @y[7]
589         pxor    @t[5], @y[3]
590         pxor    @t[4], @y[4]
591         pxor    @t[5], @t[7]            # clobber t[7] even more
592
593         pxor    @t[7], @y[5]
594         pshufd  \$0x93, @t[4], @t[4]
595         pxor    @t[7], @y[6]
596         pxor    @t[7], @y[4]
597
598         pxor    @t[5], @t[7]
599         pshufd  \$0x93, @t[5], @t[5]
600         pxor    @t[6], @t[7]            # restore t[7]
601
602         # multiplication by 0x0d
603         pxor    @y[7], @y[4]
604         pxor    @t[4], @y[7]
605         pshufd  \$0x93, @t[6], @t[6]
606         pxor    @t[0], @y[2]
607         pxor    @t[5], @y[7]
608         pxor    @t[2], @y[2]
609         pshufd  \$0x93, @t[7], @t[7]
610
611         pxor    @y[1], @y[3]
612         pxor    @t[1], @y[1]
613         pxor    @t[0], @y[0]
614         pxor    @t[0], @y[3]
615         pxor    @t[5], @y[1]
616         pxor    @t[5], @y[0]
617         pxor    @t[7], @y[1]
618         pshufd  \$0x93, @t[0], @t[0]
619         pxor    @t[6], @y[0]
620         pxor    @y[1], @y[3]
621         pxor    @t[1], @y[4]
622         pshufd  \$0x93, @t[1], @t[1]
623
624         pxor    @t[7], @y[7]
625         pxor    @t[2], @y[4]
626         pxor    @t[2], @y[5]
627         pshufd  \$0x93, @t[2], @t[2]
628         pxor    @t[6], @y[2]
629         pxor    @t[3], @t[6]            # clobber t[6]
630         pxor    @y[7], @y[4]
631         pxor    @t[6], @y[3]
632
633         pxor    @t[6], @y[6]
634         pxor    @t[5], @y[5]
635         pxor    @t[4], @y[6]
636         pshufd  \$0x93, @t[4], @t[4]
637         pxor    @t[6], @y[5]
638         pxor    @t[7], @y[6]
639         pxor    @t[3], @t[6]            # restore t[6]
640
641         pshufd  \$0x93, @t[5], @t[5]
642         pshufd  \$0x93, @t[6], @t[6]
643         pshufd  \$0x93, @t[7], @t[7]
644         pshufd  \$0x93, @t[3], @t[3]
645
646         # multiplication by 0x09
647         pxor    @y[1], @y[4]
648         pxor    @y[1], @t[1]            # t[1]=y[1]
649         pxor    @t[5], @t[0]            # clobber t[0]
650         pxor    @t[5], @t[1]
651         pxor    @t[0], @y[3]
652         pxor    @y[0], @t[0]            # t[0]=y[0]
653         pxor    @t[6], @t[1]
654         pxor    @t[7], @t[6]            # clobber t[6]
655         pxor    @t[1], @y[4]
656         pxor    @t[4], @y[7]
657         pxor    @y[4], @t[4]            # t[4]=y[4]
658         pxor    @t[3], @y[6]
659         pxor    @y[3], @t[3]            # t[3]=y[3]
660         pxor    @t[2], @y[5]
661         pxor    @y[2], @t[2]            # t[2]=y[2]
662         pxor    @t[7], @t[3]
663         pxor    @y[5], @t[5]            # t[5]=y[5]
664         pxor    @t[6], @t[2]
665         pxor    @t[6], @t[5]
666         pxor    @y[6], @t[6]            # t[6]=y[6]
667         pxor    @y[7], @t[7]            # t[7]=y[7]
668
669         movdqa  @t[0],@XMM[0]
670         movdqa  @t[1],@XMM[1]
671         movdqa  @t[2],@XMM[2]
672         movdqa  @t[3],@XMM[3]
673         movdqa  @t[4],@XMM[4]
674         movdqa  @t[5],@XMM[5]
675         movdqa  @t[6],@XMM[6]
676         movdqa  @t[7],@XMM[7]
677 ___
678 }
679
680 sub InvMixColumns {
681 my @x=@_[0..7];
682 my @t=@_[8..15];
683
684 # Thanks to Jussi Kivilinna for providing pointer to
685 #
686 # | 0e 0b 0d 09 |   | 02 03 01 01 |   | 05 00 04 00 |
687 # | 09 0e 0b 0d | = | 01 02 03 01 | x | 00 05 00 04 |
688 # | 0d 09 0e 0b |   | 01 01 02 03 |   | 04 00 05 00 |
689 # | 0b 0d 09 0e |   | 03 01 01 02 |   | 00 04 00 05 |
690
691 $code.=<<___;
692         # multiplication by 0x05-0x00-0x04-0x00
693         pshufd  \$0x4E, @x[0], @t[0]
694         pshufd  \$0x4E, @x[6], @t[6]
695         pxor    @x[0], @t[0]
696         pshufd  \$0x4E, @x[7], @t[7]
697         pxor    @x[6], @t[6]
698         pshufd  \$0x4E, @x[1], @t[1]
699         pxor    @x[7], @t[7]
700         pshufd  \$0x4E, @x[2], @t[2]
701         pxor    @x[1], @t[1]
702         pshufd  \$0x4E, @x[3], @t[3]
703         pxor    @x[2], @t[2]
704          pxor   @t[6], @x[0]
705          pxor   @t[6], @x[1]
706         pshufd  \$0x4E, @x[4], @t[4]
707         pxor    @x[3], @t[3]
708          pxor   @t[0], @x[2]
709          pxor   @t[1], @x[3]
710         pshufd  \$0x4E, @x[5], @t[5]
711         pxor    @x[4], @t[4]
712          pxor   @t[7], @x[1]
713          pxor   @t[2], @x[4]
714         pxor    @x[5], @t[5]
715
716          pxor   @t[7], @x[2]
717          pxor   @t[6], @x[3]
718          pxor   @t[6], @x[4]
719          pxor   @t[3], @x[5]
720          pxor   @t[4], @x[6]
721          pxor   @t[7], @x[4]
722          pxor   @t[7], @x[5]
723          pxor   @t[5], @x[7]
724 ___
725         &MixColumns     (@x,@t,1);      # flipped 2<->3 and 4<->6
726 }
727
728 sub aesenc {                            # not used
729 my @b=@_[0..7];
730 my @t=@_[8..15];
731 $code.=<<___;
732         movdqa  0x30($const),@t[0]      # .LSR
733 ___
734         &ShiftRows      (@b,@t[0]);
735         &Sbox           (@b,@t);
736         &MixColumns     (@b[0,1,4,6,3,7,2,5],@t);
737 }
738
739 sub aesenclast {                        # not used
740 my @b=@_[0..7];
741 my @t=@_[8..15];
742 $code.=<<___;
743         movdqa  0x40($const),@t[0]      # .LSRM0
744 ___
745         &ShiftRows      (@b,@t[0]);
746         &Sbox           (@b,@t);
747 $code.=<<___
748         pxor    0x00($key),@b[0]
749         pxor    0x10($key),@b[1]
750         pxor    0x20($key),@b[4]
751         pxor    0x30($key),@b[6]
752         pxor    0x40($key),@b[3]
753         pxor    0x50($key),@b[7]
754         pxor    0x60($key),@b[2]
755         pxor    0x70($key),@b[5]
756 ___
757 }
758
759 sub swapmove {
760 my ($a,$b,$n,$mask,$t)=@_;
761 $code.=<<___;
762         movdqa  $b,$t
763         psrlq   \$$n,$b
764         pxor    $a,$b
765         pand    $mask,$b
766         pxor    $b,$a
767         psllq   \$$n,$b
768         pxor    $t,$b
769 ___
770 }
771 sub swapmove2x {
772 my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_;
773 $code.=<<___;
774         movdqa  $b0,$t0
775         psrlq   \$$n,$b0
776          movdqa $b1,$t1
777          psrlq  \$$n,$b1
778         pxor    $a0,$b0
779          pxor   $a1,$b1
780         pand    $mask,$b0
781          pand   $mask,$b1
782         pxor    $b0,$a0
783         psllq   \$$n,$b0
784          pxor   $b1,$a1
785          psllq  \$$n,$b1
786         pxor    $t0,$b0
787          pxor   $t1,$b1
788 ___
789 }
790
791 sub bitslice {
792 my @x=reverse(@_[0..7]);
793 my ($t0,$t1,$t2,$t3)=@_[8..11];
794 $code.=<<___;
795         movdqa  0x00($const),$t0        # .LBS0
796         movdqa  0x10($const),$t1        # .LBS1
797 ___
798         &swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3);
799         &swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
800 $code.=<<___;
801         movdqa  0x20($const),$t0        # .LBS2
802 ___
803         &swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3);
804         &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
805
806         &swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3);
807         &swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3);
808 }
809
810 $code.=<<___;
811 .text
812
813 .extern asm_AES_encrypt
814 .extern asm_AES_decrypt
815
816 .type   _bsaes_encrypt8,\@abi-omnipotent
817 .align  64
818 _bsaes_encrypt8:
819         lea     .LBS0(%rip), $const     # constants table
820
821         movdqa  ($key), @XMM[9]         # round 0 key
822         lea     0x10($key), $key
823         movdqa  0x50($const), @XMM[8]   # .LM0SR
824         pxor    @XMM[9], @XMM[0]        # xor with round0 key
825         pxor    @XMM[9], @XMM[1]
826         pxor    @XMM[9], @XMM[2]
827         pxor    @XMM[9], @XMM[3]
828          pshufb @XMM[8], @XMM[0]
829          pshufb @XMM[8], @XMM[1]
830         pxor    @XMM[9], @XMM[4]
831         pxor    @XMM[9], @XMM[5]
832          pshufb @XMM[8], @XMM[2]
833          pshufb @XMM[8], @XMM[3]
834         pxor    @XMM[9], @XMM[6]
835         pxor    @XMM[9], @XMM[7]
836          pshufb @XMM[8], @XMM[4]
837          pshufb @XMM[8], @XMM[5]
838          pshufb @XMM[8], @XMM[6]
839          pshufb @XMM[8], @XMM[7]
840 _bsaes_encrypt8_bitslice:
841 ___
842         &bitslice       (@XMM[0..7, 8..11]);
843 $code.=<<___;
844         dec     $rounds
845         jmp     .Lenc_sbox
846 .align  16
847 .Lenc_loop:
848 ___
849         &ShiftRows      (@XMM[0..7, 8]);
850 $code.=".Lenc_sbox:\n";
851         &Sbox           (@XMM[0..7, 8..15]);
852 $code.=<<___;
853         dec     $rounds
854         jl      .Lenc_done
855 ___
856         &MixColumns     (@XMM[0,1,4,6,3,7,2,5, 8..15]);
857 $code.=<<___;
858         movdqa  0x30($const), @XMM[8]   # .LSR
859         jnz     .Lenc_loop
860         movdqa  0x40($const), @XMM[8]   # .LSRM0
861         jmp     .Lenc_loop
862 .align  16
863 .Lenc_done:
864 ___
865         # output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb
866         &bitslice       (@XMM[0,1,4,6,3,7,2,5, 8..11]);
867 $code.=<<___;
868         movdqa  ($key), @XMM[8]         # last round key
869         pxor    @XMM[8], @XMM[4]
870         pxor    @XMM[8], @XMM[6]
871         pxor    @XMM[8], @XMM[3]
872         pxor    @XMM[8], @XMM[7]
873         pxor    @XMM[8], @XMM[2]
874         pxor    @XMM[8], @XMM[5]
875         pxor    @XMM[8], @XMM[0]
876         pxor    @XMM[8], @XMM[1]
877         ret
878 .size   _bsaes_encrypt8,.-_bsaes_encrypt8
879
880 .type   _bsaes_decrypt8,\@abi-omnipotent
881 .align  64
882 _bsaes_decrypt8:
883         lea     .LBS0(%rip), $const     # constants table
884
885         movdqa  ($key), @XMM[9]         # round 0 key
886         lea     0x10($key), $key
887         movdqa  -0x30($const), @XMM[8]  # .LM0ISR
888         pxor    @XMM[9], @XMM[0]        # xor with round0 key
889         pxor    @XMM[9], @XMM[1]
890         pxor    @XMM[9], @XMM[2]
891         pxor    @XMM[9], @XMM[3]
892          pshufb @XMM[8], @XMM[0]
893          pshufb @XMM[8], @XMM[1]
894         pxor    @XMM[9], @XMM[4]
895         pxor    @XMM[9], @XMM[5]
896          pshufb @XMM[8], @XMM[2]
897          pshufb @XMM[8], @XMM[3]
898         pxor    @XMM[9], @XMM[6]
899         pxor    @XMM[9], @XMM[7]
900          pshufb @XMM[8], @XMM[4]
901          pshufb @XMM[8], @XMM[5]
902          pshufb @XMM[8], @XMM[6]
903          pshufb @XMM[8], @XMM[7]
904 ___
905         &bitslice       (@XMM[0..7, 8..11]);
906 $code.=<<___;
907         dec     $rounds
908         jmp     .Ldec_sbox
909 .align  16
910 .Ldec_loop:
911 ___
912         &ShiftRows      (@XMM[0..7, 8]);
913 $code.=".Ldec_sbox:\n";
914         &InvSbox        (@XMM[0..7, 8..15]);
915 $code.=<<___;
916         dec     $rounds
917         jl      .Ldec_done
918 ___
919         &InvMixColumns  (@XMM[0,1,6,4,2,7,3,5, 8..15]);
920 $code.=<<___;
921         movdqa  -0x10($const), @XMM[8]  # .LISR
922         jnz     .Ldec_loop
923         movdqa  -0x20($const), @XMM[8]  # .LISRM0
924         jmp     .Ldec_loop
925 .align  16
926 .Ldec_done:
927 ___
928         &bitslice       (@XMM[0,1,6,4,2,7,3,5, 8..11]);
929 $code.=<<___;
930         movdqa  ($key), @XMM[8]         # last round key
931         pxor    @XMM[8], @XMM[6]
932         pxor    @XMM[8], @XMM[4]
933         pxor    @XMM[8], @XMM[2]
934         pxor    @XMM[8], @XMM[7]
935         pxor    @XMM[8], @XMM[3]
936         pxor    @XMM[8], @XMM[5]
937         pxor    @XMM[8], @XMM[0]
938         pxor    @XMM[8], @XMM[1]
939         ret
940 .size   _bsaes_decrypt8,.-_bsaes_decrypt8
941 ___
942 }
943 {
944 my ($out,$inp,$rounds,$const)=("%rax","%rcx","%r10d","%r11");
945
946 sub bitslice_key {
947 my @x=reverse(@_[0..7]);
948 my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12];
949
950         &swapmove       (@x[0,1],1,$bs0,$t2,$t3);
951 $code.=<<___;
952         #&swapmove(@x[2,3],1,$t0,$t2,$t3);
953         movdqa  @x[0], @x[2]
954         movdqa  @x[1], @x[3]
955 ___
956         #&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
957
958         &swapmove2x     (@x[0,2,1,3],2,$bs1,$t2,$t3);
959 $code.=<<___;
960         #&swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
961         movdqa  @x[0], @x[4]
962         movdqa  @x[2], @x[6]
963         movdqa  @x[1], @x[5]
964         movdqa  @x[3], @x[7]
965 ___
966         &swapmove2x     (@x[0,4,1,5],4,$bs2,$t2,$t3);
967         &swapmove2x     (@x[2,6,3,7],4,$bs2,$t2,$t3);
968 }
969
970 $code.=<<___;
971 .type   _bsaes_key_convert,\@abi-omnipotent
972 .align  16
973 _bsaes_key_convert:
974         lea     .Lmasks(%rip), $const
975         movdqu  ($inp), %xmm7           # load round 0 key
976         lea     0x10($inp), $inp
977         movdqa  0x00($const), %xmm0     # 0x01...
978         movdqa  0x10($const), %xmm1     # 0x02...
979         movdqa  0x20($const), %xmm2     # 0x04...
980         movdqa  0x30($const), %xmm3     # 0x08...
981         movdqa  0x40($const), %xmm4     # .LM0
982         pcmpeqd %xmm5, %xmm5            # .LNOT
983
984         movdqu  ($inp), %xmm6           # load round 1 key
985         movdqa  %xmm7, ($out)           # save round 0 key
986         lea     0x10($out), $out
987         dec     $rounds
988         jmp     .Lkey_loop
989 .align  16
990 .Lkey_loop:
991         pshufb  %xmm4, %xmm6            # .LM0
992
993         movdqa  %xmm0,  %xmm8
994         movdqa  %xmm1,  %xmm9
995
996         pand    %xmm6,  %xmm8
997         pand    %xmm6,  %xmm9
998         movdqa  %xmm2,  %xmm10
999         pcmpeqb %xmm0,  %xmm8
1000         psllq   \$4,    %xmm0           # 0x10...
1001         movdqa  %xmm3,  %xmm11
1002         pcmpeqb %xmm1,  %xmm9
1003         psllq   \$4,    %xmm1           # 0x20...
1004
1005         pand    %xmm6,  %xmm10
1006         pand    %xmm6,  %xmm11
1007         movdqa  %xmm0,  %xmm12
1008         pcmpeqb %xmm2,  %xmm10
1009         psllq   \$4,    %xmm2           # 0x40...
1010         movdqa  %xmm1,  %xmm13
1011         pcmpeqb %xmm3,  %xmm11
1012         psllq   \$4,    %xmm3           # 0x80...
1013
1014         movdqa  %xmm2,  %xmm14
1015         movdqa  %xmm3,  %xmm15
1016          pxor   %xmm5,  %xmm8           # "pnot"
1017          pxor   %xmm5,  %xmm9
1018
1019         pand    %xmm6,  %xmm12
1020         pand    %xmm6,  %xmm13
1021          movdqa %xmm8, 0x00($out)       # write bit-sliced round key
1022         pcmpeqb %xmm0,  %xmm12
1023         psrlq   \$4,    %xmm0           # 0x01...
1024          movdqa %xmm9, 0x10($out)
1025         pcmpeqb %xmm1,  %xmm13
1026         psrlq   \$4,    %xmm1           # 0x02...
1027          lea    0x10($inp), $inp
1028
1029         pand    %xmm6,  %xmm14
1030         pand    %xmm6,  %xmm15
1031          movdqa %xmm10, 0x20($out)
1032         pcmpeqb %xmm2,  %xmm14
1033         psrlq   \$4,    %xmm2           # 0x04...
1034          movdqa %xmm11, 0x30($out)
1035         pcmpeqb %xmm3,  %xmm15
1036         psrlq   \$4,    %xmm3           # 0x08...
1037          movdqu ($inp), %xmm6           # load next round key
1038
1039         pxor    %xmm5, %xmm13           # "pnot"
1040         pxor    %xmm5, %xmm14
1041         movdqa  %xmm12, 0x40($out)
1042         movdqa  %xmm13, 0x50($out)
1043         movdqa  %xmm14, 0x60($out)
1044         movdqa  %xmm15, 0x70($out)
1045         lea     0x80($out),$out
1046         dec     $rounds
1047         jnz     .Lkey_loop
1048
1049         movdqa  0x50($const), %xmm7     # .L63
1050         #movdqa %xmm6, ($out)           # don't save last round key
1051         ret
1052 .size   _bsaes_key_convert,.-_bsaes_key_convert
1053 ___
1054 }
1055
1056 if (0 && !$win64) {     # following four functions are unsupported interface
1057                         # used for benchmarking...
1058 $code.=<<___;
1059 .globl  bsaes_enc_key_convert
1060 .type   bsaes_enc_key_convert,\@function,2
1061 .align  16
1062 bsaes_enc_key_convert:
1063         mov     240($inp),%r10d         # pass rounds
1064         mov     $inp,%rcx               # pass key
1065         mov     $out,%rax               # pass key schedule
1066         call    _bsaes_key_convert
1067         pxor    %xmm6,%xmm7             # fix up last round key
1068         movdqa  %xmm7,(%rax)            # save last round key
1069         ret
1070 .size   bsaes_enc_key_convert,.-bsaes_enc_key_convert
1071
1072 .globl  bsaes_encrypt_128
1073 .type   bsaes_encrypt_128,\@function,4
1074 .align  16
1075 bsaes_encrypt_128:
1076 .Lenc128_loop:
1077         movdqu  0x00($inp), @XMM[0]     # load input
1078         movdqu  0x10($inp), @XMM[1]
1079         movdqu  0x20($inp), @XMM[2]
1080         movdqu  0x30($inp), @XMM[3]
1081         movdqu  0x40($inp), @XMM[4]
1082         movdqu  0x50($inp), @XMM[5]
1083         movdqu  0x60($inp), @XMM[6]
1084         movdqu  0x70($inp), @XMM[7]
1085         mov     $key, %rax              # pass the $key
1086         lea     0x80($inp), $inp
1087         mov     \$10,%r10d
1088
1089         call    _bsaes_encrypt8
1090
1091         movdqu  @XMM[0], 0x00($out)     # write output
1092         movdqu  @XMM[1], 0x10($out)
1093         movdqu  @XMM[4], 0x20($out)
1094         movdqu  @XMM[6], 0x30($out)
1095         movdqu  @XMM[3], 0x40($out)
1096         movdqu  @XMM[7], 0x50($out)
1097         movdqu  @XMM[2], 0x60($out)
1098         movdqu  @XMM[5], 0x70($out)
1099         lea     0x80($out), $out
1100         sub     \$0x80,$len
1101         ja      .Lenc128_loop
1102         ret
1103 .size   bsaes_encrypt_128,.-bsaes_encrypt_128
1104
1105 .globl  bsaes_dec_key_convert
1106 .type   bsaes_dec_key_convert,\@function,2
1107 .align  16
1108 bsaes_dec_key_convert:
1109         mov     240($inp),%r10d         # pass rounds
1110         mov     $inp,%rcx               # pass key
1111         mov     $out,%rax               # pass key schedule
1112         call    _bsaes_key_convert
1113         pxor    ($out),%xmm7            # fix up round 0 key
1114         movdqa  %xmm6,(%rax)            # save last round key
1115         movdqa  %xmm7,($out)
1116         ret
1117 .size   bsaes_dec_key_convert,.-bsaes_dec_key_convert
1118
1119 .globl  bsaes_decrypt_128
1120 .type   bsaes_decrypt_128,\@function,4
1121 .align  16
1122 bsaes_decrypt_128:
1123 .Ldec128_loop:
1124         movdqu  0x00($inp), @XMM[0]     # load input
1125         movdqu  0x10($inp), @XMM[1]
1126         movdqu  0x20($inp), @XMM[2]
1127         movdqu  0x30($inp), @XMM[3]
1128         movdqu  0x40($inp), @XMM[4]
1129         movdqu  0x50($inp), @XMM[5]
1130         movdqu  0x60($inp), @XMM[6]
1131         movdqu  0x70($inp), @XMM[7]
1132         mov     $key, %rax              # pass the $key
1133         lea     0x80($inp), $inp
1134         mov     \$10,%r10d
1135
1136         call    _bsaes_decrypt8
1137
1138         movdqu  @XMM[0], 0x00($out)     # write output
1139         movdqu  @XMM[1], 0x10($out)
1140         movdqu  @XMM[6], 0x20($out)
1141         movdqu  @XMM[4], 0x30($out)
1142         movdqu  @XMM[2], 0x40($out)
1143         movdqu  @XMM[7], 0x50($out)
1144         movdqu  @XMM[3], 0x60($out)
1145         movdqu  @XMM[5], 0x70($out)
1146         lea     0x80($out), $out
1147         sub     \$0x80,$len
1148         ja      .Ldec128_loop
1149         ret
1150 .size   bsaes_decrypt_128,.-bsaes_decrypt_128
1151 ___
1152 }
1153 {
1154 ######################################################################
1155 #
1156 # OpenSSL interface
1157 #
1158 my ($arg1,$arg2,$arg3,$arg4,$arg5,$arg6)=$win64 ? ("%rcx","%rdx","%r8","%r9","%r10","%r11d")
1159                                                 : ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d");
1160 my ($inp,$out,$len,$key)=("%r12","%r13","%r14","%r15");
1161
1162 if ($ecb) {
1163 $code.=<<___;
1164 .globl  bsaes_ecb_encrypt_blocks
1165 .type   bsaes_ecb_encrypt_blocks,\@abi-omnipotent
1166 .align  16
1167 bsaes_ecb_encrypt_blocks:
1168         mov     %rsp, %rax
1169 .Lecb_enc_prologue:
1170         push    %rbp
1171         push    %rbx
1172         push    %r12
1173         push    %r13
1174         push    %r14
1175         push    %r15
1176         lea     -0x48(%rsp),%rsp
1177 ___
1178 $code.=<<___ if ($win64);
1179         lea     -0xa0(%rsp), %rsp
1180         movaps  %xmm6, 0x40(%rsp)
1181         movaps  %xmm7, 0x50(%rsp)
1182         movaps  %xmm8, 0x60(%rsp)
1183         movaps  %xmm9, 0x70(%rsp)
1184         movaps  %xmm10, 0x80(%rsp)
1185         movaps  %xmm11, 0x90(%rsp)
1186         movaps  %xmm12, 0xa0(%rsp)
1187         movaps  %xmm13, 0xb0(%rsp)
1188         movaps  %xmm14, 0xc0(%rsp)
1189         movaps  %xmm15, 0xd0(%rsp)
1190 .Lecb_enc_body:
1191 ___
1192 $code.=<<___;
1193         mov     %rsp,%rbp               # backup %rsp
1194         mov     240($arg4),%eax         # rounds
1195         mov     $arg1,$inp              # backup arguments
1196         mov     $arg2,$out
1197         mov     $arg3,$len
1198         mov     $arg4,$key
1199         cmp     \$8,$arg3
1200         jb      .Lecb_enc_short
1201
1202         mov     %eax,%ebx               # backup rounds
1203         shl     \$7,%rax                # 128 bytes per inner round key
1204         sub     \$`128-32`,%rax         # size of bit-sliced key schedule
1205         sub     %rax,%rsp
1206         mov     %rsp,%rax               # pass key schedule
1207         mov     $key,%rcx               # pass key
1208         mov     %ebx,%r10d              # pass rounds
1209         call    _bsaes_key_convert
1210         pxor    %xmm6,%xmm7             # fix up last round key
1211         movdqa  %xmm7,(%rax)            # save last round key
1212
1213         sub     \$8,$len
1214 .Lecb_enc_loop:
1215         movdqu  0x00($inp), @XMM[0]     # load input
1216         movdqu  0x10($inp), @XMM[1]
1217         movdqu  0x20($inp), @XMM[2]
1218         movdqu  0x30($inp), @XMM[3]
1219         movdqu  0x40($inp), @XMM[4]
1220         movdqu  0x50($inp), @XMM[5]
1221         mov     %rsp, %rax              # pass key schedule
1222         movdqu  0x60($inp), @XMM[6]
1223         mov     %ebx,%r10d              # pass rounds
1224         movdqu  0x70($inp), @XMM[7]
1225         lea     0x80($inp), $inp
1226
1227         call    _bsaes_encrypt8
1228
1229         movdqu  @XMM[0], 0x00($out)     # write output
1230         movdqu  @XMM[1], 0x10($out)
1231         movdqu  @XMM[4], 0x20($out)
1232         movdqu  @XMM[6], 0x30($out)
1233         movdqu  @XMM[3], 0x40($out)
1234         movdqu  @XMM[7], 0x50($out)
1235         movdqu  @XMM[2], 0x60($out)
1236         movdqu  @XMM[5], 0x70($out)
1237         lea     0x80($out), $out
1238         sub     \$8,$len
1239         jnc     .Lecb_enc_loop
1240
1241         add     \$8,$len
1242         jz      .Lecb_enc_done
1243
1244         movdqu  0x00($inp), @XMM[0]     # load input
1245         mov     %rsp, %rax              # pass key schedule
1246         mov     %ebx,%r10d              # pass rounds
1247         cmp     \$2,$len
1248         jb      .Lecb_enc_one
1249         movdqu  0x10($inp), @XMM[1]
1250         je      .Lecb_enc_two
1251         movdqu  0x20($inp), @XMM[2]
1252         cmp     \$4,$len
1253         jb      .Lecb_enc_three
1254         movdqu  0x30($inp), @XMM[3]
1255         je      .Lecb_enc_four
1256         movdqu  0x40($inp), @XMM[4]
1257         cmp     \$6,$len
1258         jb      .Lecb_enc_five
1259         movdqu  0x50($inp), @XMM[5]
1260         je      .Lecb_enc_six
1261         movdqu  0x60($inp), @XMM[6]
1262         call    _bsaes_encrypt8
1263         movdqu  @XMM[0], 0x00($out)     # write output
1264         movdqu  @XMM[1], 0x10($out)
1265         movdqu  @XMM[4], 0x20($out)
1266         movdqu  @XMM[6], 0x30($out)
1267         movdqu  @XMM[3], 0x40($out)
1268         movdqu  @XMM[7], 0x50($out)
1269         movdqu  @XMM[2], 0x60($out)
1270         jmp     .Lecb_enc_done
1271 .align  16
1272 .Lecb_enc_six:
1273         call    _bsaes_encrypt8
1274         movdqu  @XMM[0], 0x00($out)     # write output
1275         movdqu  @XMM[1], 0x10($out)
1276         movdqu  @XMM[4], 0x20($out)
1277         movdqu  @XMM[6], 0x30($out)
1278         movdqu  @XMM[3], 0x40($out)
1279         movdqu  @XMM[7], 0x50($out)
1280         jmp     .Lecb_enc_done
1281 .align  16
1282 .Lecb_enc_five:
1283         call    _bsaes_encrypt8
1284         movdqu  @XMM[0], 0x00($out)     # write output
1285         movdqu  @XMM[1], 0x10($out)
1286         movdqu  @XMM[4], 0x20($out)
1287         movdqu  @XMM[6], 0x30($out)
1288         movdqu  @XMM[3], 0x40($out)
1289         jmp     .Lecb_enc_done
1290 .align  16
1291 .Lecb_enc_four:
1292         call    _bsaes_encrypt8
1293         movdqu  @XMM[0], 0x00($out)     # write output
1294         movdqu  @XMM[1], 0x10($out)
1295         movdqu  @XMM[4], 0x20($out)
1296         movdqu  @XMM[6], 0x30($out)
1297         jmp     .Lecb_enc_done
1298 .align  16
1299 .Lecb_enc_three:
1300         call    _bsaes_encrypt8
1301         movdqu  @XMM[0], 0x00($out)     # write output
1302         movdqu  @XMM[1], 0x10($out)
1303         movdqu  @XMM[4], 0x20($out)
1304         jmp     .Lecb_enc_done
1305 .align  16
1306 .Lecb_enc_two:
1307         call    _bsaes_encrypt8
1308         movdqu  @XMM[0], 0x00($out)     # write output
1309         movdqu  @XMM[1], 0x10($out)
1310         jmp     .Lecb_enc_done
1311 .align  16
1312 .Lecb_enc_one:
1313         call    _bsaes_encrypt8
1314         movdqu  @XMM[0], 0x00($out)     # write output
1315         jmp     .Lecb_enc_done
1316 .align  16
1317 .Lecb_enc_short:
1318         lea     ($inp), $arg1
1319         lea     ($out), $arg2
1320         lea     ($key), $arg3
1321         call    asm_AES_encrypt
1322         lea     16($inp), $inp
1323         lea     16($out), $out
1324         dec     $len
1325         jnz     .Lecb_enc_short
1326
1327 .Lecb_enc_done:
1328         lea     (%rsp),%rax
1329         pxor    %xmm0, %xmm0
1330 .Lecb_enc_bzero:                        # wipe key schedule [if any]
1331         movdqa  %xmm0, 0x00(%rax)
1332         movdqa  %xmm0, 0x10(%rax)
1333         lea     0x20(%rax), %rax
1334         cmp     %rax, %rbp
1335         jb      .Lecb_enc_bzero
1336
1337         lea     0x78(%rbp),%rax
1338 ___
1339 $code.=<<___ if ($win64);
1340         movaps  0x40(%rbp), %xmm6
1341         movaps  0x50(%rbp), %xmm7
1342         movaps  0x60(%rbp), %xmm8
1343         movaps  0x70(%rbp), %xmm9
1344         movaps  0x80(%rbp), %xmm10
1345         movaps  0x90(%rbp), %xmm11
1346         movaps  0xa0(%rbp), %xmm12
1347         movaps  0xb0(%rbp), %xmm13
1348         movaps  0xc0(%rbp), %xmm14
1349         movaps  0xd0(%rbp), %xmm15
1350         lea     0xa0(%rax), %rax
1351 .Lecb_enc_tail:
1352 ___
1353 $code.=<<___;
1354         mov     -48(%rax), %r15
1355         mov     -40(%rax), %r14
1356         mov     -32(%rax), %r13
1357         mov     -24(%rax), %r12
1358         mov     -16(%rax), %rbx
1359         mov     -8(%rax), %rbp
1360         lea     (%rax), %rsp            # restore %rsp
1361 .Lecb_enc_epilogue:
1362         ret
1363 .size   bsaes_ecb_encrypt_blocks,.-bsaes_ecb_encrypt_blocks
1364
1365 .globl  bsaes_ecb_decrypt_blocks
1366 .type   bsaes_ecb_decrypt_blocks,\@abi-omnipotent
1367 .align  16
1368 bsaes_ecb_decrypt_blocks:
1369         mov     %rsp, %rax
1370 .Lecb_dec_prologue:
1371         push    %rbp
1372         push    %rbx
1373         push    %r12
1374         push    %r13
1375         push    %r14
1376         push    %r15
1377         lea     -0x48(%rsp),%rsp
1378 ___
1379 $code.=<<___ if ($win64);
1380         lea     -0xa0(%rsp), %rsp
1381         movaps  %xmm6, 0x40(%rsp)
1382         movaps  %xmm7, 0x50(%rsp)
1383         movaps  %xmm8, 0x60(%rsp)
1384         movaps  %xmm9, 0x70(%rsp)
1385         movaps  %xmm10, 0x80(%rsp)
1386         movaps  %xmm11, 0x90(%rsp)
1387         movaps  %xmm12, 0xa0(%rsp)
1388         movaps  %xmm13, 0xb0(%rsp)
1389         movaps  %xmm14, 0xc0(%rsp)
1390         movaps  %xmm15, 0xd0(%rsp)
1391 .Lecb_dec_body:
1392 ___
1393 $code.=<<___;
1394         mov     %rsp,%rbp               # backup %rsp
1395         mov     240($arg4),%eax         # rounds
1396         mov     $arg1,$inp              # backup arguments
1397         mov     $arg2,$out
1398         mov     $arg3,$len
1399         mov     $arg4,$key
1400         cmp     \$8,$arg3
1401         jb      .Lecb_dec_short
1402
1403         mov     %eax,%ebx               # backup rounds
1404         shl     \$7,%rax                # 128 bytes per inner round key
1405         sub     \$`128-32`,%rax         # size of bit-sliced key schedule
1406         sub     %rax,%rsp
1407         mov     %rsp,%rax               # pass key schedule
1408         mov     $key,%rcx               # pass key
1409         mov     %ebx,%r10d              # pass rounds
1410         call    _bsaes_key_convert
1411         pxor    (%rsp),%xmm7            # fix up 0 round key
1412         movdqa  %xmm6,(%rax)            # save last round key
1413         movdqa  %xmm7,(%rsp)
1414
1415         sub     \$8,$len
1416 .Lecb_dec_loop:
1417         movdqu  0x00($inp), @XMM[0]     # load input
1418         movdqu  0x10($inp), @XMM[1]
1419         movdqu  0x20($inp), @XMM[2]
1420         movdqu  0x30($inp), @XMM[3]
1421         movdqu  0x40($inp), @XMM[4]
1422         movdqu  0x50($inp), @XMM[5]
1423         mov     %rsp, %rax              # pass key schedule
1424         movdqu  0x60($inp), @XMM[6]
1425         mov     %ebx,%r10d              # pass rounds
1426         movdqu  0x70($inp), @XMM[7]
1427         lea     0x80($inp), $inp
1428
1429         call    _bsaes_decrypt8
1430
1431         movdqu  @XMM[0], 0x00($out)     # write output
1432         movdqu  @XMM[1], 0x10($out)
1433         movdqu  @XMM[6], 0x20($out)
1434         movdqu  @XMM[4], 0x30($out)
1435         movdqu  @XMM[2], 0x40($out)
1436         movdqu  @XMM[7], 0x50($out)
1437         movdqu  @XMM[3], 0x60($out)
1438         movdqu  @XMM[5], 0x70($out)
1439         lea     0x80($out), $out
1440         sub     \$8,$len
1441         jnc     .Lecb_dec_loop
1442
1443         add     \$8,$len
1444         jz      .Lecb_dec_done
1445
1446         movdqu  0x00($inp), @XMM[0]     # load input
1447         mov     %rsp, %rax              # pass key schedule
1448         mov     %ebx,%r10d              # pass rounds
1449         cmp     \$2,$len
1450         jb      .Lecb_dec_one
1451         movdqu  0x10($inp), @XMM[1]
1452         je      .Lecb_dec_two
1453         movdqu  0x20($inp), @XMM[2]
1454         cmp     \$4,$len
1455         jb      .Lecb_dec_three
1456         movdqu  0x30($inp), @XMM[3]
1457         je      .Lecb_dec_four
1458         movdqu  0x40($inp), @XMM[4]
1459         cmp     \$6,$len
1460         jb      .Lecb_dec_five
1461         movdqu  0x50($inp), @XMM[5]
1462         je      .Lecb_dec_six
1463         movdqu  0x60($inp), @XMM[6]
1464         call    _bsaes_decrypt8
1465         movdqu  @XMM[0], 0x00($out)     # write output
1466         movdqu  @XMM[1], 0x10($out)
1467         movdqu  @XMM[6], 0x20($out)
1468         movdqu  @XMM[4], 0x30($out)
1469         movdqu  @XMM[2], 0x40($out)
1470         movdqu  @XMM[7], 0x50($out)
1471         movdqu  @XMM[3], 0x60($out)
1472         jmp     .Lecb_dec_done
1473 .align  16
1474 .Lecb_dec_six:
1475         call    _bsaes_decrypt8
1476         movdqu  @XMM[0], 0x00($out)     # write output
1477         movdqu  @XMM[1], 0x10($out)
1478         movdqu  @XMM[6], 0x20($out)
1479         movdqu  @XMM[4], 0x30($out)
1480         movdqu  @XMM[2], 0x40($out)
1481         movdqu  @XMM[7], 0x50($out)
1482         jmp     .Lecb_dec_done
1483 .align  16
1484 .Lecb_dec_five:
1485         call    _bsaes_decrypt8
1486         movdqu  @XMM[0], 0x00($out)     # write output
1487         movdqu  @XMM[1], 0x10($out)
1488         movdqu  @XMM[6], 0x20($out)
1489         movdqu  @XMM[4], 0x30($out)
1490         movdqu  @XMM[2], 0x40($out)
1491         jmp     .Lecb_dec_done
1492 .align  16
1493 .Lecb_dec_four:
1494         call    _bsaes_decrypt8
1495         movdqu  @XMM[0], 0x00($out)     # write output
1496         movdqu  @XMM[1], 0x10($out)
1497         movdqu  @XMM[6], 0x20($out)
1498         movdqu  @XMM[4], 0x30($out)
1499         jmp     .Lecb_dec_done
1500 .align  16
1501 .Lecb_dec_three:
1502         call    _bsaes_decrypt8
1503         movdqu  @XMM[0], 0x00($out)     # write output
1504         movdqu  @XMM[1], 0x10($out)
1505         movdqu  @XMM[6], 0x20($out)
1506         jmp     .Lecb_dec_done
1507 .align  16
1508 .Lecb_dec_two:
1509         call    _bsaes_decrypt8
1510         movdqu  @XMM[0], 0x00($out)     # write output
1511         movdqu  @XMM[1], 0x10($out)
1512         jmp     .Lecb_dec_done
1513 .align  16
1514 .Lecb_dec_one:
1515         call    _bsaes_decrypt8
1516         movdqu  @XMM[0], 0x00($out)     # write output
1517         jmp     .Lecb_dec_done
1518 .align  16
1519 .Lecb_dec_short:
1520         lea     ($inp), $arg1
1521         lea     ($out), $arg2
1522         lea     ($key), $arg3
1523         call    asm_AES_decrypt
1524         lea     16($inp), $inp
1525         lea     16($out), $out
1526         dec     $len
1527         jnz     .Lecb_dec_short
1528
1529 .Lecb_dec_done:
1530         lea     (%rsp),%rax
1531         pxor    %xmm0, %xmm0
1532 .Lecb_dec_bzero:                        # wipe key schedule [if any]
1533         movdqa  %xmm0, 0x00(%rax)
1534         movdqa  %xmm0, 0x10(%rax)
1535         lea     0x20(%rax), %rax
1536         cmp     %rax, %rbp
1537         jb      .Lecb_dec_bzero
1538
1539         lea     0x78(%rbp),%rax
1540 ___
1541 $code.=<<___ if ($win64);
1542         movaps  0x40(%rbp), %xmm6
1543         movaps  0x50(%rbp), %xmm7
1544         movaps  0x60(%rbp), %xmm8
1545         movaps  0x70(%rbp), %xmm9
1546         movaps  0x80(%rbp), %xmm10
1547         movaps  0x90(%rbp), %xmm11
1548         movaps  0xa0(%rbp), %xmm12
1549         movaps  0xb0(%rbp), %xmm13
1550         movaps  0xc0(%rbp), %xmm14
1551         movaps  0xd0(%rbp), %xmm15
1552         lea     0xa0(%rax), %rax
1553 .Lecb_dec_tail:
1554 ___
1555 $code.=<<___;
1556         mov     -48(%rax), %r15
1557         mov     -40(%rax), %r14
1558         mov     -32(%rax), %r13
1559         mov     -24(%rax), %r12
1560         mov     -16(%rax), %rbx
1561         mov     -8(%rax), %rbp
1562         lea     (%rax), %rsp            # restore %rsp
1563 .Lecb_dec_epilogue:
1564         ret
1565 .size   bsaes_ecb_decrypt_blocks,.-bsaes_ecb_decrypt_blocks
1566 ___
1567 }
1568 $code.=<<___;
1569 .extern asm_AES_cbc_encrypt
1570 .globl  bsaes_cbc_encrypt
1571 .type   bsaes_cbc_encrypt,\@abi-omnipotent
1572 .align  16
1573 bsaes_cbc_encrypt:
1574 ___
1575 $code.=<<___ if ($win64);
1576         mov     48(%rsp),$arg6          # pull direction flag
1577 ___
1578 $code.=<<___;
1579         cmp     \$0,$arg6
1580         jne     asm_AES_cbc_encrypt
1581         cmp     \$128,$arg3
1582         jb      asm_AES_cbc_encrypt
1583
1584         mov     %rsp, %rax
1585 .Lcbc_dec_prologue:
1586         push    %rbp
1587         push    %rbx
1588         push    %r12
1589         push    %r13
1590         push    %r14
1591         push    %r15
1592         lea     -0x48(%rsp), %rsp
1593 ___
1594 $code.=<<___ if ($win64);
1595         mov     0xa0(%rsp),$arg5        # pull ivp
1596         lea     -0xa0(%rsp), %rsp
1597         movaps  %xmm6, 0x40(%rsp)
1598         movaps  %xmm7, 0x50(%rsp)
1599         movaps  %xmm8, 0x60(%rsp)
1600         movaps  %xmm9, 0x70(%rsp)
1601         movaps  %xmm10, 0x80(%rsp)
1602         movaps  %xmm11, 0x90(%rsp)
1603         movaps  %xmm12, 0xa0(%rsp)
1604         movaps  %xmm13, 0xb0(%rsp)
1605         movaps  %xmm14, 0xc0(%rsp)
1606         movaps  %xmm15, 0xd0(%rsp)
1607 .Lcbc_dec_body:
1608 ___
1609 $code.=<<___;
1610         mov     %rsp, %rbp              # backup %rsp
1611         mov     240($arg4), %eax        # rounds
1612         mov     $arg1, $inp             # backup arguments
1613         mov     $arg2, $out
1614         mov     $arg3, $len
1615         mov     $arg4, $key
1616         mov     $arg5, %rbx
1617         shr     \$4, $len               # bytes to blocks
1618
1619         mov     %eax, %edx              # rounds
1620         shl     \$7, %rax               # 128 bytes per inner round key
1621         sub     \$`128-32`, %rax        # size of bit-sliced key schedule
1622         sub     %rax, %rsp
1623
1624         mov     %rsp, %rax              # pass key schedule
1625         mov     $key, %rcx              # pass key
1626         mov     %edx, %r10d             # pass rounds
1627         call    _bsaes_key_convert
1628         pxor    (%rsp),%xmm7            # fix up 0 round key
1629         movdqa  %xmm6,(%rax)            # save last round key
1630         movdqa  %xmm7,(%rsp)
1631
1632         movdqu  (%rbx), @XMM[15]        # load IV
1633         sub     \$8,$len
1634 .Lcbc_dec_loop:
1635         movdqu  0x00($inp), @XMM[0]     # load input
1636         movdqu  0x10($inp), @XMM[1]
1637         movdqu  0x20($inp), @XMM[2]
1638         movdqu  0x30($inp), @XMM[3]
1639         movdqu  0x40($inp), @XMM[4]
1640         movdqu  0x50($inp), @XMM[5]
1641         mov     %rsp, %rax              # pass key schedule
1642         movdqu  0x60($inp), @XMM[6]
1643         mov     %edx,%r10d              # pass rounds
1644         movdqu  0x70($inp), @XMM[7]
1645         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1646
1647         call    _bsaes_decrypt8
1648
1649         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1650         movdqu  0x00($inp), @XMM[8]     # re-load input
1651         movdqu  0x10($inp), @XMM[9]
1652         pxor    @XMM[8], @XMM[1]
1653         movdqu  0x20($inp), @XMM[10]
1654         pxor    @XMM[9], @XMM[6]
1655         movdqu  0x30($inp), @XMM[11]
1656         pxor    @XMM[10], @XMM[4]
1657         movdqu  0x40($inp), @XMM[12]
1658         pxor    @XMM[11], @XMM[2]
1659         movdqu  0x50($inp), @XMM[13]
1660         pxor    @XMM[12], @XMM[7]
1661         movdqu  0x60($inp), @XMM[14]
1662         pxor    @XMM[13], @XMM[3]
1663         movdqu  0x70($inp), @XMM[15]    # IV
1664         pxor    @XMM[14], @XMM[5]
1665         movdqu  @XMM[0], 0x00($out)     # write output
1666         lea     0x80($inp), $inp
1667         movdqu  @XMM[1], 0x10($out)
1668         movdqu  @XMM[6], 0x20($out)
1669         movdqu  @XMM[4], 0x30($out)
1670         movdqu  @XMM[2], 0x40($out)
1671         movdqu  @XMM[7], 0x50($out)
1672         movdqu  @XMM[3], 0x60($out)
1673         movdqu  @XMM[5], 0x70($out)
1674         lea     0x80($out), $out
1675         sub     \$8,$len
1676         jnc     .Lcbc_dec_loop
1677
1678         add     \$8,$len
1679         jz      .Lcbc_dec_done
1680
1681         movdqu  0x00($inp), @XMM[0]     # load input
1682         mov     %rsp, %rax              # pass key schedule
1683         mov     %edx, %r10d             # pass rounds
1684         cmp     \$2,$len
1685         jb      .Lcbc_dec_one
1686         movdqu  0x10($inp), @XMM[1]
1687         je      .Lcbc_dec_two
1688         movdqu  0x20($inp), @XMM[2]
1689         cmp     \$4,$len
1690         jb      .Lcbc_dec_three
1691         movdqu  0x30($inp), @XMM[3]
1692         je      .Lcbc_dec_four
1693         movdqu  0x40($inp), @XMM[4]
1694         cmp     \$6,$len
1695         jb      .Lcbc_dec_five
1696         movdqu  0x50($inp), @XMM[5]
1697         je      .Lcbc_dec_six
1698         movdqu  0x60($inp), @XMM[6]
1699         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1700         call    _bsaes_decrypt8
1701         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1702         movdqu  0x00($inp), @XMM[8]     # re-load input
1703         movdqu  0x10($inp), @XMM[9]
1704         pxor    @XMM[8], @XMM[1]
1705         movdqu  0x20($inp), @XMM[10]
1706         pxor    @XMM[9], @XMM[6]
1707         movdqu  0x30($inp), @XMM[11]
1708         pxor    @XMM[10], @XMM[4]
1709         movdqu  0x40($inp), @XMM[12]
1710         pxor    @XMM[11], @XMM[2]
1711         movdqu  0x50($inp), @XMM[13]
1712         pxor    @XMM[12], @XMM[7]
1713         movdqu  0x60($inp), @XMM[15]    # IV
1714         pxor    @XMM[13], @XMM[3]
1715         movdqu  @XMM[0], 0x00($out)     # write output
1716         movdqu  @XMM[1], 0x10($out)
1717         movdqu  @XMM[6], 0x20($out)
1718         movdqu  @XMM[4], 0x30($out)
1719         movdqu  @XMM[2], 0x40($out)
1720         movdqu  @XMM[7], 0x50($out)
1721         movdqu  @XMM[3], 0x60($out)
1722         jmp     .Lcbc_dec_done
1723 .align  16
1724 .Lcbc_dec_six:
1725         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1726         call    _bsaes_decrypt8
1727         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1728         movdqu  0x00($inp), @XMM[8]     # re-load input
1729         movdqu  0x10($inp), @XMM[9]
1730         pxor    @XMM[8], @XMM[1]
1731         movdqu  0x20($inp), @XMM[10]
1732         pxor    @XMM[9], @XMM[6]
1733         movdqu  0x30($inp), @XMM[11]
1734         pxor    @XMM[10], @XMM[4]
1735         movdqu  0x40($inp), @XMM[12]
1736         pxor    @XMM[11], @XMM[2]
1737         movdqu  0x50($inp), @XMM[15]    # IV
1738         pxor    @XMM[12], @XMM[7]
1739         movdqu  @XMM[0], 0x00($out)     # write output
1740         movdqu  @XMM[1], 0x10($out)
1741         movdqu  @XMM[6], 0x20($out)
1742         movdqu  @XMM[4], 0x30($out)
1743         movdqu  @XMM[2], 0x40($out)
1744         movdqu  @XMM[7], 0x50($out)
1745         jmp     .Lcbc_dec_done
1746 .align  16
1747 .Lcbc_dec_five:
1748         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1749         call    _bsaes_decrypt8
1750         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1751         movdqu  0x00($inp), @XMM[8]     # re-load input
1752         movdqu  0x10($inp), @XMM[9]
1753         pxor    @XMM[8], @XMM[1]
1754         movdqu  0x20($inp), @XMM[10]
1755         pxor    @XMM[9], @XMM[6]
1756         movdqu  0x30($inp), @XMM[11]
1757         pxor    @XMM[10], @XMM[4]
1758         movdqu  0x40($inp), @XMM[15]    # IV
1759         pxor    @XMM[11], @XMM[2]
1760         movdqu  @XMM[0], 0x00($out)     # write output
1761         movdqu  @XMM[1], 0x10($out)
1762         movdqu  @XMM[6], 0x20($out)
1763         movdqu  @XMM[4], 0x30($out)
1764         movdqu  @XMM[2], 0x40($out)
1765         jmp     .Lcbc_dec_done
1766 .align  16
1767 .Lcbc_dec_four:
1768         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1769         call    _bsaes_decrypt8
1770         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1771         movdqu  0x00($inp), @XMM[8]     # re-load input
1772         movdqu  0x10($inp), @XMM[9]
1773         pxor    @XMM[8], @XMM[1]
1774         movdqu  0x20($inp), @XMM[10]
1775         pxor    @XMM[9], @XMM[6]
1776         movdqu  0x30($inp), @XMM[15]    # IV
1777         pxor    @XMM[10], @XMM[4]
1778         movdqu  @XMM[0], 0x00($out)     # write output
1779         movdqu  @XMM[1], 0x10($out)
1780         movdqu  @XMM[6], 0x20($out)
1781         movdqu  @XMM[4], 0x30($out)
1782         jmp     .Lcbc_dec_done
1783 .align  16
1784 .Lcbc_dec_three:
1785         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1786         call    _bsaes_decrypt8
1787         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1788         movdqu  0x00($inp), @XMM[8]     # re-load input
1789         movdqu  0x10($inp), @XMM[9]
1790         pxor    @XMM[8], @XMM[1]
1791         movdqu  0x20($inp), @XMM[15]    # IV
1792         pxor    @XMM[9], @XMM[6]
1793         movdqu  @XMM[0], 0x00($out)     # write output
1794         movdqu  @XMM[1], 0x10($out)
1795         movdqu  @XMM[6], 0x20($out)
1796         jmp     .Lcbc_dec_done
1797 .align  16
1798 .Lcbc_dec_two:
1799         movdqa  @XMM[15], 0x20(%rbp)    # put aside IV
1800         call    _bsaes_decrypt8
1801         pxor    0x20(%rbp), @XMM[0]     # ^= IV
1802         movdqu  0x00($inp), @XMM[8]     # re-load input
1803         movdqu  0x10($inp), @XMM[15]    # IV
1804         pxor    @XMM[8], @XMM[1]
1805         movdqu  @XMM[0], 0x00($out)     # write output
1806         movdqu  @XMM[1], 0x10($out)
1807         jmp     .Lcbc_dec_done
1808 .align  16
1809 .Lcbc_dec_one:
1810         lea     ($inp), $arg1
1811         lea     0x20(%rbp), $arg2       # buffer output
1812         lea     ($key), $arg3
1813         call    asm_AES_decrypt         # doesn't touch %xmm
1814         pxor    0x20(%rbp), @XMM[15]    # ^= IV
1815         movdqu  @XMM[15], ($out)        # write output
1816         movdqa  @XMM[0], @XMM[15]       # IV
1817
1818 .Lcbc_dec_done:
1819         movdqu  @XMM[15], (%rbx)        # return IV
1820         lea     (%rsp), %rax
1821         pxor    %xmm0, %xmm0
1822 .Lcbc_dec_bzero:                        # wipe key schedule [if any]
1823         movdqa  %xmm0, 0x00(%rax)
1824         movdqa  %xmm0, 0x10(%rax)
1825         lea     0x20(%rax), %rax
1826         cmp     %rax, %rbp
1827         ja      .Lcbc_dec_bzero
1828
1829         lea     0x78(%rbp),%rax
1830 ___
1831 $code.=<<___ if ($win64);
1832         movaps  0x40(%rbp), %xmm6
1833         movaps  0x50(%rbp), %xmm7
1834         movaps  0x60(%rbp), %xmm8
1835         movaps  0x70(%rbp), %xmm9
1836         movaps  0x80(%rbp), %xmm10
1837         movaps  0x90(%rbp), %xmm11
1838         movaps  0xa0(%rbp), %xmm12
1839         movaps  0xb0(%rbp), %xmm13
1840         movaps  0xc0(%rbp), %xmm14
1841         movaps  0xd0(%rbp), %xmm15
1842         lea     0xa0(%rax), %rax
1843 .Lcbc_dec_tail:
1844 ___
1845 $code.=<<___;
1846         mov     -48(%rax), %r15
1847         mov     -40(%rax), %r14
1848         mov     -32(%rax), %r13
1849         mov     -24(%rax), %r12
1850         mov     -16(%rax), %rbx
1851         mov     -8(%rax), %rbp
1852         lea     (%rax), %rsp            # restore %rsp
1853 .Lcbc_dec_epilogue:
1854         ret
1855 .size   bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
1856
1857 .globl  bsaes_ctr32_encrypt_blocks
1858 .type   bsaes_ctr32_encrypt_blocks,\@abi-omnipotent
1859 .align  16
1860 bsaes_ctr32_encrypt_blocks:
1861         mov     %rsp, %rax
1862 .Lctr_enc_prologue:
1863         push    %rbp
1864         push    %rbx
1865         push    %r12
1866         push    %r13
1867         push    %r14
1868         push    %r15
1869         lea     -0x48(%rsp), %rsp
1870 ___
1871 $code.=<<___ if ($win64);
1872         mov     0xa0(%rsp),$arg5        # pull ivp
1873         lea     -0xa0(%rsp), %rsp
1874         movaps  %xmm6, 0x40(%rsp)
1875         movaps  %xmm7, 0x50(%rsp)
1876         movaps  %xmm8, 0x60(%rsp)
1877         movaps  %xmm9, 0x70(%rsp)
1878         movaps  %xmm10, 0x80(%rsp)
1879         movaps  %xmm11, 0x90(%rsp)
1880         movaps  %xmm12, 0xa0(%rsp)
1881         movaps  %xmm13, 0xb0(%rsp)
1882         movaps  %xmm14, 0xc0(%rsp)
1883         movaps  %xmm15, 0xd0(%rsp)
1884 .Lctr_enc_body:
1885 ___
1886 $code.=<<___;
1887         mov     %rsp, %rbp              # backup %rsp
1888         movdqu  ($arg5), %xmm0          # load counter
1889         mov     240($arg4), %eax        # rounds
1890         mov     $arg1, $inp             # backup arguments
1891         mov     $arg2, $out
1892         mov     $arg3, $len
1893         mov     $arg4, $key
1894         movdqa  %xmm0, 0x20(%rbp)       # copy counter
1895         cmp     \$8, $arg3
1896         jb      .Lctr_enc_short
1897
1898         mov     %eax, %ebx              # rounds
1899         shl     \$7, %rax               # 128 bytes per inner round key
1900         sub     \$`128-32`, %rax        # size of bit-sliced key schedule
1901         sub     %rax, %rsp
1902
1903         mov     %rsp, %rax              # pass key schedule
1904         mov     $key, %rcx              # pass key
1905         mov     %ebx, %r10d             # pass rounds
1906         call    _bsaes_key_convert
1907         pxor    %xmm6,%xmm7             # fix up last round key
1908         movdqa  %xmm7,(%rax)            # save last round key
1909
1910         movdqa  (%rsp), @XMM[9]         # load round0 key
1911         lea     .LADD1(%rip), %r11
1912         movdqa  0x20(%rbp), @XMM[0]     # counter copy
1913         movdqa  -0x20(%r11), @XMM[8]    # .LSWPUP
1914         pshufb  @XMM[8], @XMM[9]        # byte swap upper part
1915         pshufb  @XMM[8], @XMM[0]
1916         movdqa  @XMM[9], (%rsp)         # save adjusted round0 key
1917         jmp     .Lctr_enc_loop
1918 .align  16
1919 .Lctr_enc_loop:
1920         movdqa  @XMM[0], 0x20(%rbp)     # save counter
1921         movdqa  @XMM[0], @XMM[1]        # prepare 8 counter values
1922         movdqa  @XMM[0], @XMM[2]
1923         paddd   0x00(%r11), @XMM[1]     # .LADD1
1924         movdqa  @XMM[0], @XMM[3]
1925         paddd   0x10(%r11), @XMM[2]     # .LADD2
1926         movdqa  @XMM[0], @XMM[4]
1927         paddd   0x20(%r11), @XMM[3]     # .LADD3
1928         movdqa  @XMM[0], @XMM[5]
1929         paddd   0x30(%r11), @XMM[4]     # .LADD4
1930         movdqa  @XMM[0], @XMM[6]
1931         paddd   0x40(%r11), @XMM[5]     # .LADD5
1932         movdqa  @XMM[0], @XMM[7]
1933         paddd   0x50(%r11), @XMM[6]     # .LADD6
1934         paddd   0x60(%r11), @XMM[7]     # .LADD7
1935
1936         # Borrow prologue from _bsaes_encrypt8 to use the opportunity
1937         # to flip byte order in 32-bit counter
1938         movdqa  (%rsp), @XMM[9]         # round 0 key
1939         lea     0x10(%rsp), %rax        # pass key schedule
1940         movdqa  -0x10(%r11), @XMM[8]    # .LSWPUPM0SR
1941         pxor    @XMM[9], @XMM[0]        # xor with round0 key
1942         pxor    @XMM[9], @XMM[1]
1943         pxor    @XMM[9], @XMM[2]
1944         pxor    @XMM[9], @XMM[3]
1945          pshufb @XMM[8], @XMM[0]
1946          pshufb @XMM[8], @XMM[1]
1947         pxor    @XMM[9], @XMM[4]
1948         pxor    @XMM[9], @XMM[5]
1949          pshufb @XMM[8], @XMM[2]
1950          pshufb @XMM[8], @XMM[3]
1951         pxor    @XMM[9], @XMM[6]
1952         pxor    @XMM[9], @XMM[7]
1953          pshufb @XMM[8], @XMM[4]
1954          pshufb @XMM[8], @XMM[5]
1955          pshufb @XMM[8], @XMM[6]
1956          pshufb @XMM[8], @XMM[7]
1957         lea     .LBS0(%rip), %r11       # constants table
1958         mov     %ebx,%r10d              # pass rounds
1959
1960         call    _bsaes_encrypt8_bitslice
1961
1962         sub     \$8,$len
1963         jc      .Lctr_enc_loop_done
1964
1965         movdqu  0x00($inp), @XMM[8]     # load input
1966         movdqu  0x10($inp), @XMM[9]
1967         movdqu  0x20($inp), @XMM[10]
1968         movdqu  0x30($inp), @XMM[11]
1969         movdqu  0x40($inp), @XMM[12]
1970         movdqu  0x50($inp), @XMM[13]
1971         movdqu  0x60($inp), @XMM[14]
1972         movdqu  0x70($inp), @XMM[15]
1973         lea     0x80($inp),$inp
1974         pxor    @XMM[0], @XMM[8]
1975         movdqa  0x20(%rbp), @XMM[0]     # load counter
1976         pxor    @XMM[9], @XMM[1]
1977         movdqu  @XMM[8], 0x00($out)     # write output
1978         pxor    @XMM[10], @XMM[4]
1979         movdqu  @XMM[1], 0x10($out)
1980         pxor    @XMM[11], @XMM[6]
1981         movdqu  @XMM[4], 0x20($out)
1982         pxor    @XMM[12], @XMM[3]
1983         movdqu  @XMM[6], 0x30($out)
1984         pxor    @XMM[13], @XMM[7]
1985         movdqu  @XMM[3], 0x40($out)
1986         pxor    @XMM[14], @XMM[2]
1987         movdqu  @XMM[7], 0x50($out)
1988         pxor    @XMM[15], @XMM[5]
1989         movdqu  @XMM[2], 0x60($out)
1990         lea     .LADD1(%rip), %r11
1991         movdqu  @XMM[5], 0x70($out)
1992         lea     0x80($out), $out
1993         paddd   0x70(%r11), @XMM[0]     # .LADD8
1994         jnz     .Lctr_enc_loop
1995
1996         jmp     .Lctr_enc_done
1997 .align  16
1998 .Lctr_enc_loop_done:
1999         add     \$8, $len
2000         movdqu  0x00($inp), @XMM[8]     # load input
2001         pxor    @XMM[8], @XMM[0]
2002         movdqu  @XMM[0], 0x00($out)     # write output
2003         cmp     \$2,$len
2004         jb      .Lctr_enc_done
2005         movdqu  0x10($inp), @XMM[9]
2006         pxor    @XMM[9], @XMM[1]
2007         movdqu  @XMM[1], 0x10($out)
2008         je      .Lctr_enc_done
2009         movdqu  0x20($inp), @XMM[10]
2010         pxor    @XMM[10], @XMM[4]
2011         movdqu  @XMM[4], 0x20($out)
2012         cmp     \$4,$len
2013         jb      .Lctr_enc_done
2014         movdqu  0x30($inp), @XMM[11]
2015         pxor    @XMM[11], @XMM[6]
2016         movdqu  @XMM[6], 0x30($out)
2017         je      .Lctr_enc_done
2018         movdqu  0x40($inp), @XMM[12]
2019         pxor    @XMM[12], @XMM[3]
2020         movdqu  @XMM[3], 0x40($out)
2021         cmp     \$6,$len
2022         jb      .Lctr_enc_done
2023         movdqu  0x50($inp), @XMM[13]
2024         pxor    @XMM[13], @XMM[7]
2025         movdqu  @XMM[7], 0x50($out)
2026         je      .Lctr_enc_done
2027         movdqu  0x60($inp), @XMM[14]
2028         pxor    @XMM[14], @XMM[2]
2029         movdqu  @XMM[2], 0x60($out)
2030         jmp     .Lctr_enc_done
2031
2032 .align  16
2033 .Lctr_enc_short:
2034         lea     0x20(%rbp), $arg1
2035         lea     0x30(%rbp), $arg2
2036         lea     ($key), $arg3
2037         call    asm_AES_encrypt
2038         movdqu  ($inp), @XMM[1]
2039         lea     16($inp), $inp
2040         mov     0x2c(%rbp), %eax        # load 32-bit counter
2041         bswap   %eax
2042         pxor    0x30(%rbp), @XMM[1]
2043         inc     %eax                    # increment
2044         movdqu  @XMM[1], ($out)
2045         bswap   %eax
2046         lea     16($out), $out
2047         mov     %eax, 0x2c(%rsp)        # save 32-bit counter
2048         dec     $len
2049         jnz     .Lctr_enc_short
2050
2051 .Lctr_enc_done:
2052         lea     (%rsp), %rax
2053         pxor    %xmm0, %xmm0
2054 .Lctr_enc_bzero:                        # wipe key schedule [if any]
2055         movdqa  %xmm0, 0x00(%rax)
2056         movdqa  %xmm0, 0x10(%rax)
2057         lea     0x20(%rax), %rax
2058         cmp     %rax, %rbp
2059         ja      .Lctr_enc_bzero
2060
2061         lea     0x78(%rbp),%rax
2062 ___
2063 $code.=<<___ if ($win64);
2064         movaps  0x40(%rbp), %xmm6
2065         movaps  0x50(%rbp), %xmm7
2066         movaps  0x60(%rbp), %xmm8
2067         movaps  0x70(%rbp), %xmm9
2068         movaps  0x80(%rbp), %xmm10
2069         movaps  0x90(%rbp), %xmm11
2070         movaps  0xa0(%rbp), %xmm12
2071         movaps  0xb0(%rbp), %xmm13
2072         movaps  0xc0(%rbp), %xmm14
2073         movaps  0xd0(%rbp), %xmm15
2074         lea     0xa0(%rax), %rax
2075 .Lctr_enc_tail:
2076 ___
2077 $code.=<<___;
2078         mov     -48(%rax), %r15
2079         mov     -40(%rax), %r14
2080         mov     -32(%rax), %r13
2081         mov     -24(%rax), %r12
2082         mov     -16(%rax), %rbx
2083         mov     -8(%rax), %rbp
2084         lea     (%rax), %rsp            # restore %rsp
2085 .Lctr_enc_epilogue:
2086         ret
2087 .size   bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
2088 ___
2089 ######################################################################
2090 # void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len,
2091 #       const AES_KEY *key1, const AES_KEY *key2,
2092 #       const unsigned char iv[16]);
2093 #
2094 my ($twmask,$twres,$twtmp)=@XMM[13..15];
2095 $arg6=~s/d$//;
2096
2097 $code.=<<___;
2098 .globl  bsaes_xts_encrypt
2099 .type   bsaes_xts_encrypt,\@abi-omnipotent
2100 .align  16
2101 bsaes_xts_encrypt:
2102         mov     %rsp, %rax
2103 .Lxts_enc_prologue:
2104         push    %rbp
2105         push    %rbx
2106         push    %r12
2107         push    %r13
2108         push    %r14
2109         push    %r15
2110         lea     -0x48(%rsp), %rsp
2111 ___
2112 $code.=<<___ if ($win64);
2113         mov     0xa0(%rsp),$arg5        # pull key2
2114         mov     0xa8(%rsp),$arg6        # pull ivp
2115         lea     -0xa0(%rsp), %rsp
2116         movaps  %xmm6, 0x40(%rsp)
2117         movaps  %xmm7, 0x50(%rsp)
2118         movaps  %xmm8, 0x60(%rsp)
2119         movaps  %xmm9, 0x70(%rsp)
2120         movaps  %xmm10, 0x80(%rsp)
2121         movaps  %xmm11, 0x90(%rsp)
2122         movaps  %xmm12, 0xa0(%rsp)
2123         movaps  %xmm13, 0xb0(%rsp)
2124         movaps  %xmm14, 0xc0(%rsp)
2125         movaps  %xmm15, 0xd0(%rsp)
2126 .Lxts_enc_body:
2127 ___
2128 $code.=<<___;
2129         mov     %rsp, %rbp              # backup %rsp
2130         mov     $arg1, $inp             # backup arguments
2131         mov     $arg2, $out
2132         mov     $arg3, $len
2133         mov     $arg4, $key
2134
2135         lea     ($arg6), $arg1
2136         lea     0x20(%rbp), $arg2
2137         lea     ($arg5), $arg3
2138         call    asm_AES_encrypt         # generate initial tweak
2139
2140         mov     240($key), %eax         # rounds
2141         mov     $len, %rbx              # backup $len
2142
2143         mov     %eax, %edx              # rounds
2144         shl     \$7, %rax               # 128 bytes per inner round key
2145         sub     \$`128-32`, %rax        # size of bit-sliced key schedule
2146         sub     %rax, %rsp
2147
2148         mov     %rsp, %rax              # pass key schedule
2149         mov     $key, %rcx              # pass key
2150         mov     %edx, %r10d             # pass rounds
2151         call    _bsaes_key_convert
2152         pxor    %xmm6, %xmm7            # fix up last round key
2153         movdqa  %xmm7, (%rax)           # save last round key
2154
2155         and     \$-16, $len
2156         sub     \$0x80, %rsp            # place for tweak[8]
2157         movdqa  0x20(%rbp), @XMM[7]     # initial tweak
2158
2159         pxor    $twtmp, $twtmp
2160         movdqa  .Lxts_magic(%rip), $twmask
2161         pcmpgtd @XMM[7], $twtmp         # broadcast upper bits
2162
2163         sub     \$0x80, $len
2164         jc      .Lxts_enc_short
2165         jmp     .Lxts_enc_loop
2166
2167 .align  16
2168 .Lxts_enc_loop:
2169 ___
2170     for ($i=0;$i<7;$i++) {
2171     $code.=<<___;
2172         pshufd  \$0x13, $twtmp, $twres
2173         pxor    $twtmp, $twtmp
2174         movdqa  @XMM[7], @XMM[$i]
2175         movdqa  @XMM[7], `0x10*$i`(%rsp)# save tweak[$i]
2176         paddq   @XMM[7], @XMM[7]        # psllq 1,$tweak
2177         pand    $twmask, $twres         # isolate carry and residue
2178         pcmpgtd @XMM[7], $twtmp         # broadcast upper bits
2179         pxor    $twres, @XMM[7]
2180 ___
2181     $code.=<<___ if ($i>=1);
2182         movdqu  `0x10*($i-1)`($inp), @XMM[8+$i-1]
2183 ___
2184     $code.=<<___ if ($i>=2);
2185         pxor    @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[]
2186 ___
2187     }
2188 $code.=<<___;
2189         movdqu  0x60($inp), @XMM[8+6]
2190         pxor    @XMM[8+5], @XMM[5]
2191         movdqu  0x70($inp), @XMM[8+7]
2192         lea     0x80($inp), $inp
2193         movdqa  @XMM[7], 0x70(%rsp)
2194         pxor    @XMM[8+6], @XMM[6]
2195         lea     0x80(%rsp), %rax        # pass key schedule
2196         pxor    @XMM[8+7], @XMM[7]
2197         mov     %edx, %r10d             # pass rounds
2198
2199         call    _bsaes_encrypt8
2200
2201         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2202         pxor    0x10(%rsp), @XMM[1]
2203         movdqu  @XMM[0], 0x00($out)     # write output
2204         pxor    0x20(%rsp), @XMM[4]
2205         movdqu  @XMM[1], 0x10($out)
2206         pxor    0x30(%rsp), @XMM[6]
2207         movdqu  @XMM[4], 0x20($out)
2208         pxor    0x40(%rsp), @XMM[3]
2209         movdqu  @XMM[6], 0x30($out)
2210         pxor    0x50(%rsp), @XMM[7]
2211         movdqu  @XMM[3], 0x40($out)
2212         pxor    0x60(%rsp), @XMM[2]
2213         movdqu  @XMM[7], 0x50($out)
2214         pxor    0x70(%rsp), @XMM[5]
2215         movdqu  @XMM[2], 0x60($out)
2216         movdqu  @XMM[5], 0x70($out)
2217         lea     0x80($out), $out
2218
2219         movdqa  0x70(%rsp), @XMM[7]     # prepare next iteration tweak
2220         pxor    $twtmp, $twtmp
2221         movdqa  .Lxts_magic(%rip), $twmask
2222         pcmpgtd @XMM[7], $twtmp
2223         pshufd  \$0x13, $twtmp, $twres
2224         pxor    $twtmp, $twtmp
2225         paddq   @XMM[7], @XMM[7]        # psllq 1,$tweak
2226         pand    $twmask, $twres         # isolate carry and residue
2227         pcmpgtd @XMM[7], $twtmp         # broadcast upper bits
2228         pxor    $twres, @XMM[7]
2229
2230         sub     \$0x80,$len
2231         jnc     .Lxts_enc_loop
2232
2233 .Lxts_enc_short:
2234         add     \$0x80, $len
2235         jz      .Lxts_enc_done
2236 ___
2237     for ($i=0;$i<7;$i++) {
2238     $code.=<<___;
2239         pshufd  \$0x13, $twtmp, $twres
2240         pxor    $twtmp, $twtmp
2241         movdqa  @XMM[7], @XMM[$i]
2242         movdqa  @XMM[7], `0x10*$i`(%rsp)# save tweak[$i]
2243         paddq   @XMM[7], @XMM[7]        # psllq 1,$tweak
2244         pand    $twmask, $twres         # isolate carry and residue
2245         pcmpgtd @XMM[7], $twtmp         # broadcast upper bits
2246         pxor    $twres, @XMM[7]
2247 ___
2248     $code.=<<___ if ($i>=1);
2249         movdqu  `0x10*($i-1)`($inp), @XMM[8+$i-1]
2250         cmp     \$`0x10*$i`,$len
2251         je      .Lxts_enc_$i
2252 ___
2253     $code.=<<___ if ($i>=2);
2254         pxor    @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[]
2255 ___
2256     }
2257 $code.=<<___;
2258         movdqu  0x60($inp), @XMM[8+6]
2259         pxor    @XMM[8+5], @XMM[5]
2260         movdqa  @XMM[7], 0x70(%rsp)
2261         lea     0x70($inp), $inp
2262         pxor    @XMM[8+6], @XMM[6]
2263         lea     0x80(%rsp), %rax        # pass key schedule
2264         mov     %edx, %r10d             # pass rounds
2265
2266         call    _bsaes_encrypt8
2267
2268         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2269         pxor    0x10(%rsp), @XMM[1]
2270         movdqu  @XMM[0], 0x00($out)     # write output
2271         pxor    0x20(%rsp), @XMM[4]
2272         movdqu  @XMM[1], 0x10($out)
2273         pxor    0x30(%rsp), @XMM[6]
2274         movdqu  @XMM[4], 0x20($out)
2275         pxor    0x40(%rsp), @XMM[3]
2276         movdqu  @XMM[6], 0x30($out)
2277         pxor    0x50(%rsp), @XMM[7]
2278         movdqu  @XMM[3], 0x40($out)
2279         pxor    0x60(%rsp), @XMM[2]
2280         movdqu  @XMM[7], 0x50($out)
2281         movdqu  @XMM[2], 0x60($out)
2282         lea     0x70($out), $out
2283
2284         movdqa  0x70(%rsp), @XMM[7]     # next iteration tweak
2285         jmp     .Lxts_enc_done
2286 .align  16
2287 .Lxts_enc_6:
2288         pxor    @XMM[8+4], @XMM[4]
2289         lea     0x60($inp), $inp
2290         pxor    @XMM[8+5], @XMM[5]
2291         lea     0x80(%rsp), %rax        # pass key schedule
2292         mov     %edx, %r10d             # pass rounds
2293
2294         call    _bsaes_encrypt8
2295
2296         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2297         pxor    0x10(%rsp), @XMM[1]
2298         movdqu  @XMM[0], 0x00($out)     # write output
2299         pxor    0x20(%rsp), @XMM[4]
2300         movdqu  @XMM[1], 0x10($out)
2301         pxor    0x30(%rsp), @XMM[6]
2302         movdqu  @XMM[4], 0x20($out)
2303         pxor    0x40(%rsp), @XMM[3]
2304         movdqu  @XMM[6], 0x30($out)
2305         pxor    0x50(%rsp), @XMM[7]
2306         movdqu  @XMM[3], 0x40($out)
2307         movdqu  @XMM[7], 0x50($out)
2308         lea     0x60($out), $out
2309
2310         movdqa  0x60(%rsp), @XMM[7]     # next iteration tweak
2311         jmp     .Lxts_enc_done
2312 .align  16
2313 .Lxts_enc_5:
2314         pxor    @XMM[8+3], @XMM[3]
2315         lea     0x50($inp), $inp
2316         pxor    @XMM[8+4], @XMM[4]
2317         lea     0x80(%rsp), %rax        # pass key schedule
2318         mov     %edx, %r10d             # pass rounds
2319
2320         call    _bsaes_encrypt8
2321
2322         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2323         pxor    0x10(%rsp), @XMM[1]
2324         movdqu  @XMM[0], 0x00($out)     # write output
2325         pxor    0x20(%rsp), @XMM[4]
2326         movdqu  @XMM[1], 0x10($out)
2327         pxor    0x30(%rsp), @XMM[6]
2328         movdqu  @XMM[4], 0x20($out)
2329         pxor    0x40(%rsp), @XMM[3]
2330         movdqu  @XMM[6], 0x30($out)
2331         movdqu  @XMM[3], 0x40($out)
2332         lea     0x50($out), $out
2333
2334         movdqa  0x50(%rsp), @XMM[7]     # next iteration tweak
2335         jmp     .Lxts_enc_done
2336 .align  16
2337 .Lxts_enc_4:
2338         pxor    @XMM[8+2], @XMM[2]
2339         lea     0x40($inp), $inp
2340         pxor    @XMM[8+3], @XMM[3]
2341         lea     0x80(%rsp), %rax        # pass key schedule
2342         mov     %edx, %r10d             # pass rounds
2343
2344         call    _bsaes_encrypt8
2345
2346         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2347         pxor    0x10(%rsp), @XMM[1]
2348         movdqu  @XMM[0], 0x00($out)     # write output
2349         pxor    0x20(%rsp), @XMM[4]
2350         movdqu  @XMM[1], 0x10($out)
2351         pxor    0x30(%rsp), @XMM[6]
2352         movdqu  @XMM[4], 0x20($out)
2353         movdqu  @XMM[6], 0x30($out)
2354         lea     0x40($out), $out
2355
2356         movdqa  0x40(%rsp), @XMM[7]     # next iteration tweak
2357         jmp     .Lxts_enc_done
2358 .align  16
2359 .Lxts_enc_3:
2360         pxor    @XMM[8+1], @XMM[1]
2361         lea     0x30($inp), $inp
2362         pxor    @XMM[8+2], @XMM[2]
2363         lea     0x80(%rsp), %rax        # pass key schedule
2364         mov     %edx, %r10d             # pass rounds
2365
2366         call    _bsaes_encrypt8
2367
2368         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2369         pxor    0x10(%rsp), @XMM[1]
2370         movdqu  @XMM[0], 0x00($out)     # write output
2371         pxor    0x20(%rsp), @XMM[4]
2372         movdqu  @XMM[1], 0x10($out)
2373         movdqu  @XMM[4], 0x20($out)
2374         lea     0x30($out), $out
2375
2376         movdqa  0x30(%rsp), @XMM[7]     # next iteration tweak
2377         jmp     .Lxts_enc_done
2378 .align  16
2379 .Lxts_enc_2:
2380         pxor    @XMM[8+0], @XMM[0]
2381         lea     0x20($inp), $inp
2382         pxor    @XMM[8+1], @XMM[1]
2383         lea     0x80(%rsp), %rax        # pass key schedule
2384         mov     %edx, %r10d             # pass rounds
2385
2386         call    _bsaes_encrypt8
2387
2388         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2389         pxor    0x10(%rsp), @XMM[1]
2390         movdqu  @XMM[0], 0x00($out)     # write output
2391         movdqu  @XMM[1], 0x10($out)
2392         lea     0x20($out), $out
2393
2394         movdqa  0x20(%rsp), @XMM[7]     # next iteration tweak
2395         jmp     .Lxts_enc_done
2396 .align  16
2397 .Lxts_enc_1:
2398         pxor    @XMM[0], @XMM[8]
2399         lea     0x10($inp), $inp
2400         movdqa  @XMM[8], 0x20(%rbp)
2401         lea     0x20(%rbp), $arg1
2402         lea     0x20(%rbp), $arg2
2403         lea     ($key), $arg3
2404         call    asm_AES_encrypt         # doesn't touch %xmm
2405         pxor    0x20(%rbp), @XMM[0]     # ^= tweak[]
2406         #pxor   @XMM[8], @XMM[0]
2407         #lea    0x80(%rsp), %rax        # pass key schedule
2408         #mov    %edx, %r10d             # pass rounds
2409         #call   _bsaes_encrypt8
2410         #pxor   0x00(%rsp), @XMM[0]     # ^= tweak[]
2411         movdqu  @XMM[0], 0x00($out)     # write output
2412         lea     0x10($out), $out
2413
2414         movdqa  0x10(%rsp), @XMM[7]     # next iteration tweak
2415
2416 .Lxts_enc_done:
2417         and     \$15, %ebx
2418         jz      .Lxts_enc_ret
2419         mov     $out, %rdx
2420
2421 .Lxts_enc_steal:
2422         movzb   ($inp), %eax
2423         movzb   -16(%rdx), %ecx
2424         lea     1($inp), $inp
2425         mov     %al, -16(%rdx)
2426         mov     %cl, 0(%rdx)
2427         lea     1(%rdx), %rdx
2428         sub     \$1,%ebx
2429         jnz     .Lxts_enc_steal
2430
2431         movdqu  -16($out), @XMM[0]
2432         lea     0x20(%rbp), $arg1
2433         pxor    @XMM[7], @XMM[0]
2434         lea     0x20(%rbp), $arg2
2435         movdqa  @XMM[0], 0x20(%rbp)
2436         lea     ($key), $arg3
2437         call    asm_AES_encrypt         # doesn't touch %xmm
2438         pxor    0x20(%rbp), @XMM[7]
2439         movdqu  @XMM[7], -16($out)
2440
2441 .Lxts_enc_ret:
2442         lea     (%rsp), %rax
2443         pxor    %xmm0, %xmm0
2444 .Lxts_enc_bzero:                        # wipe key schedule [if any]
2445         movdqa  %xmm0, 0x00(%rax)
2446         movdqa  %xmm0, 0x10(%rax)
2447         lea     0x20(%rax), %rax
2448         cmp     %rax, %rbp
2449         ja      .Lxts_enc_bzero
2450
2451         lea     0x78(%rbp),%rax
2452 ___
2453 $code.=<<___ if ($win64);
2454         movaps  0x40(%rbp), %xmm6
2455         movaps  0x50(%rbp), %xmm7
2456         movaps  0x60(%rbp), %xmm8
2457         movaps  0x70(%rbp), %xmm9
2458         movaps  0x80(%rbp), %xmm10
2459         movaps  0x90(%rbp), %xmm11
2460         movaps  0xa0(%rbp), %xmm12
2461         movaps  0xb0(%rbp), %xmm13
2462         movaps  0xc0(%rbp), %xmm14
2463         movaps  0xd0(%rbp), %xmm15
2464         lea     0xa0(%rax), %rax
2465 .Lxts_enc_tail:
2466 ___
2467 $code.=<<___;
2468         mov     -48(%rax), %r15
2469         mov     -40(%rax), %r14
2470         mov     -32(%rax), %r13
2471         mov     -24(%rax), %r12
2472         mov     -16(%rax), %rbx
2473         mov     -8(%rax), %rbp
2474         lea     (%rax), %rsp            # restore %rsp
2475 .Lxts_enc_epilogue:
2476         ret
2477 .size   bsaes_xts_encrypt,.-bsaes_xts_encrypt
2478
2479 .globl  bsaes_xts_decrypt
2480 .type   bsaes_xts_decrypt,\@abi-omnipotent
2481 .align  16
2482 bsaes_xts_decrypt:
2483         mov     %rsp, %rax
2484 .Lxts_dec_prologue:
2485         push    %rbp
2486         push    %rbx
2487         push    %r12
2488         push    %r13
2489         push    %r14
2490         push    %r15
2491         lea     -0x48(%rsp), %rsp
2492 ___
2493 $code.=<<___ if ($win64);
2494         mov     0xa0(%rsp),$arg5        # pull key2
2495         mov     0xa8(%rsp),$arg6        # pull ivp
2496         lea     -0xa0(%rsp), %rsp
2497         movaps  %xmm6, 0x40(%rsp)
2498         movaps  %xmm7, 0x50(%rsp)
2499         movaps  %xmm8, 0x60(%rsp)
2500         movaps  %xmm9, 0x70(%rsp)
2501         movaps  %xmm10, 0x80(%rsp)
2502         movaps  %xmm11, 0x90(%rsp)
2503         movaps  %xmm12, 0xa0(%rsp)
2504         movaps  %xmm13, 0xb0(%rsp)
2505         movaps  %xmm14, 0xc0(%rsp)
2506         movaps  %xmm15, 0xd0(%rsp)
2507 .Lxts_dec_body:
2508 ___
2509 $code.=<<___;
2510         mov     %rsp, %rbp              # backup %rsp
2511         mov     $arg1, $inp             # backup arguments
2512         mov     $arg2, $out
2513         mov     $arg3, $len
2514         mov     $arg4, $key
2515
2516         lea     ($arg6), $arg1
2517         lea     0x20(%rbp), $arg2
2518         lea     ($arg5), $arg3
2519         call    asm_AES_encrypt         # generate initial tweak
2520
2521         mov     240($key), %eax         # rounds
2522         mov     $len, %rbx              # backup $len
2523
2524         mov     %eax, %edx              # rounds
2525         shl     \$7, %rax               # 128 bytes per inner round key
2526         sub     \$`128-32`, %rax        # size of bit-sliced key schedule
2527         sub     %rax, %rsp
2528
2529         mov     %rsp, %rax              # pass key schedule
2530         mov     $key, %rcx              # pass key
2531         mov     %edx, %r10d             # pass rounds
2532         call    _bsaes_key_convert
2533         pxor    (%rsp), %xmm7           # fix up round 0 key
2534         movdqa  %xmm6, (%rax)           # save last round key
2535         movdqa  %xmm7, (%rsp)
2536
2537         xor     %eax, %eax              # if ($len%16) len-=16;
2538         and     \$-16, $len
2539         test    \$15, %ebx
2540         setnz   %al
2541         shl     \$4, %rax
2542         sub     %rax, $len
2543
2544         sub     \$0x80, %rsp            # place for tweak[8]
2545         movdqa  0x20(%rbp), @XMM[7]     # initial tweak
2546
2547         pxor    $twtmp, $twtmp
2548         movdqa  .Lxts_magic(%rip), $twmask
2549         pcmpgtd @XMM[7], $twtmp         # broadcast upper bits
2550
2551         sub     \$0x80, $len
2552         jc      .Lxts_dec_short
2553         jmp     .Lxts_dec_loop
2554
2555 .align  16
2556 .Lxts_dec_loop:
2557 ___
2558     for ($i=0;$i<7;$i++) {
2559     $code.=<<___;
2560         pshufd  \$0x13, $twtmp, $twres
2561         pxor    $twtmp, $twtmp
2562         movdqa  @XMM[7], @XMM[$i]
2563         movdqa  @XMM[7], `0x10*$i`(%rsp)# save tweak[$i]
2564         paddq   @XMM[7], @XMM[7]        # psllq 1,$tweak
2565         pand    $twmask, $twres         # isolate carry and residue
2566         pcmpgtd @XMM[7], $twtmp         # broadcast upper bits
2567         pxor    $twres, @XMM[7]
2568 ___
2569     $code.=<<___ if ($i>=1);
2570         movdqu  `0x10*($i-1)`($inp), @XMM[8+$i-1]
2571 ___
2572     $code.=<<___ if ($i>=2);
2573         pxor    @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[]
2574 ___
2575     }
2576 $code.=<<___;
2577         movdqu  0x60($inp), @XMM[8+6]
2578         pxor    @XMM[8+5], @XMM[5]
2579         movdqu  0x70($inp), @XMM[8+7]
2580         lea     0x80($inp), $inp
2581         movdqa  @XMM[7], 0x70(%rsp)
2582         pxor    @XMM[8+6], @XMM[6]
2583         lea     0x80(%rsp), %rax        # pass key schedule
2584         pxor    @XMM[8+7], @XMM[7]
2585         mov     %edx, %r10d             # pass rounds
2586
2587         call    _bsaes_decrypt8
2588
2589         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2590         pxor    0x10(%rsp), @XMM[1]
2591         movdqu  @XMM[0], 0x00($out)     # write output
2592         pxor    0x20(%rsp), @XMM[6]
2593         movdqu  @XMM[1], 0x10($out)
2594         pxor    0x30(%rsp), @XMM[4]
2595         movdqu  @XMM[6], 0x20($out)
2596         pxor    0x40(%rsp), @XMM[2]
2597         movdqu  @XMM[4], 0x30($out)
2598         pxor    0x50(%rsp), @XMM[7]
2599         movdqu  @XMM[2], 0x40($out)
2600         pxor    0x60(%rsp), @XMM[3]
2601         movdqu  @XMM[7], 0x50($out)
2602         pxor    0x70(%rsp), @XMM[5]
2603         movdqu  @XMM[3], 0x60($out)
2604         movdqu  @XMM[5], 0x70($out)
2605         lea     0x80($out), $out
2606
2607         movdqa  0x70(%rsp), @XMM[7]     # prepare next iteration tweak
2608         pxor    $twtmp, $twtmp
2609         movdqa  .Lxts_magic(%rip), $twmask
2610         pcmpgtd @XMM[7], $twtmp
2611         pshufd  \$0x13, $twtmp, $twres
2612         pxor    $twtmp, $twtmp
2613         paddq   @XMM[7], @XMM[7]        # psllq 1,$tweak
2614         pand    $twmask, $twres         # isolate carry and residue
2615         pcmpgtd @XMM[7], $twtmp         # broadcast upper bits
2616         pxor    $twres, @XMM[7]
2617
2618         sub     \$0x80,$len
2619         jnc     .Lxts_dec_loop
2620
2621 .Lxts_dec_short:
2622         add     \$0x80, $len
2623         jz      .Lxts_dec_done
2624 ___
2625     for ($i=0;$i<7;$i++) {
2626     $code.=<<___;
2627         pshufd  \$0x13, $twtmp, $twres
2628         pxor    $twtmp, $twtmp
2629         movdqa  @XMM[7], @XMM[$i]
2630         movdqa  @XMM[7], `0x10*$i`(%rsp)# save tweak[$i]
2631         paddq   @XMM[7], @XMM[7]        # psllq 1,$tweak
2632         pand    $twmask, $twres         # isolate carry and residue
2633         pcmpgtd @XMM[7], $twtmp         # broadcast upper bits
2634         pxor    $twres, @XMM[7]
2635 ___
2636     $code.=<<___ if ($i>=1);
2637         movdqu  `0x10*($i-1)`($inp), @XMM[8+$i-1]
2638         cmp     \$`0x10*$i`,$len
2639         je      .Lxts_dec_$i
2640 ___
2641     $code.=<<___ if ($i>=2);
2642         pxor    @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[]
2643 ___
2644     }
2645 $code.=<<___;
2646         movdqu  0x60($inp), @XMM[8+6]
2647         pxor    @XMM[8+5], @XMM[5]
2648         movdqa  @XMM[7], 0x70(%rsp)
2649         lea     0x70($inp), $inp
2650         pxor    @XMM[8+6], @XMM[6]
2651         lea     0x80(%rsp), %rax        # pass key schedule
2652         mov     %edx, %r10d             # pass rounds
2653
2654         call    _bsaes_decrypt8
2655
2656         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2657         pxor    0x10(%rsp), @XMM[1]
2658         movdqu  @XMM[0], 0x00($out)     # write output
2659         pxor    0x20(%rsp), @XMM[6]
2660         movdqu  @XMM[1], 0x10($out)
2661         pxor    0x30(%rsp), @XMM[4]
2662         movdqu  @XMM[6], 0x20($out)
2663         pxor    0x40(%rsp), @XMM[2]
2664         movdqu  @XMM[4], 0x30($out)
2665         pxor    0x50(%rsp), @XMM[7]
2666         movdqu  @XMM[2], 0x40($out)
2667         pxor    0x60(%rsp), @XMM[3]
2668         movdqu  @XMM[7], 0x50($out)
2669         movdqu  @XMM[3], 0x60($out)
2670         lea     0x70($out), $out
2671
2672         movdqa  0x70(%rsp), @XMM[7]     # next iteration tweak
2673         jmp     .Lxts_dec_done
2674 .align  16
2675 .Lxts_dec_6:
2676         pxor    @XMM[8+4], @XMM[4]
2677         lea     0x60($inp), $inp
2678         pxor    @XMM[8+5], @XMM[5]
2679         lea     0x80(%rsp), %rax        # pass key schedule
2680         mov     %edx, %r10d             # pass rounds
2681
2682         call    _bsaes_decrypt8
2683
2684         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2685         pxor    0x10(%rsp), @XMM[1]
2686         movdqu  @XMM[0], 0x00($out)     # write output
2687         pxor    0x20(%rsp), @XMM[6]
2688         movdqu  @XMM[1], 0x10($out)
2689         pxor    0x30(%rsp), @XMM[4]
2690         movdqu  @XMM[6], 0x20($out)
2691         pxor    0x40(%rsp), @XMM[2]
2692         movdqu  @XMM[4], 0x30($out)
2693         pxor    0x50(%rsp), @XMM[7]
2694         movdqu  @XMM[2], 0x40($out)
2695         movdqu  @XMM[7], 0x50($out)
2696         lea     0x60($out), $out
2697
2698         movdqa  0x60(%rsp), @XMM[7]     # next iteration tweak
2699         jmp     .Lxts_dec_done
2700 .align  16
2701 .Lxts_dec_5:
2702         pxor    @XMM[8+3], @XMM[3]
2703         lea     0x50($inp), $inp
2704         pxor    @XMM[8+4], @XMM[4]
2705         lea     0x80(%rsp), %rax        # pass key schedule
2706         mov     %edx, %r10d             # pass rounds
2707
2708         call    _bsaes_decrypt8
2709
2710         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2711         pxor    0x10(%rsp), @XMM[1]
2712         movdqu  @XMM[0], 0x00($out)     # write output
2713         pxor    0x20(%rsp), @XMM[6]
2714         movdqu  @XMM[1], 0x10($out)
2715         pxor    0x30(%rsp), @XMM[4]
2716         movdqu  @XMM[6], 0x20($out)
2717         pxor    0x40(%rsp), @XMM[2]
2718         movdqu  @XMM[4], 0x30($out)
2719         movdqu  @XMM[2], 0x40($out)
2720         lea     0x50($out), $out
2721
2722         movdqa  0x50(%rsp), @XMM[7]     # next iteration tweak
2723         jmp     .Lxts_dec_done
2724 .align  16
2725 .Lxts_dec_4:
2726         pxor    @XMM[8+2], @XMM[2]
2727         lea     0x40($inp), $inp
2728         pxor    @XMM[8+3], @XMM[3]
2729         lea     0x80(%rsp), %rax        # pass key schedule
2730         mov     %edx, %r10d             # pass rounds
2731
2732         call    _bsaes_decrypt8
2733
2734         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2735         pxor    0x10(%rsp), @XMM[1]
2736         movdqu  @XMM[0], 0x00($out)     # write output
2737         pxor    0x20(%rsp), @XMM[6]
2738         movdqu  @XMM[1], 0x10($out)
2739         pxor    0x30(%rsp), @XMM[4]
2740         movdqu  @XMM[6], 0x20($out)
2741         movdqu  @XMM[4], 0x30($out)
2742         lea     0x40($out), $out
2743
2744         movdqa  0x40(%rsp), @XMM[7]     # next iteration tweak
2745         jmp     .Lxts_dec_done
2746 .align  16
2747 .Lxts_dec_3:
2748         pxor    @XMM[8+1], @XMM[1]
2749         lea     0x30($inp), $inp
2750         pxor    @XMM[8+2], @XMM[2]
2751         lea     0x80(%rsp), %rax        # pass key schedule
2752         mov     %edx, %r10d             # pass rounds
2753
2754         call    _bsaes_decrypt8
2755
2756         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2757         pxor    0x10(%rsp), @XMM[1]
2758         movdqu  @XMM[0], 0x00($out)     # write output
2759         pxor    0x20(%rsp), @XMM[6]
2760         movdqu  @XMM[1], 0x10($out)
2761         movdqu  @XMM[6], 0x20($out)
2762         lea     0x30($out), $out
2763
2764         movdqa  0x30(%rsp), @XMM[7]     # next iteration tweak
2765         jmp     .Lxts_dec_done
2766 .align  16
2767 .Lxts_dec_2:
2768         pxor    @XMM[8+0], @XMM[0]
2769         lea     0x20($inp), $inp
2770         pxor    @XMM[8+1], @XMM[1]
2771         lea     0x80(%rsp), %rax        # pass key schedule
2772         mov     %edx, %r10d             # pass rounds
2773
2774         call    _bsaes_decrypt8
2775
2776         pxor    0x00(%rsp), @XMM[0]     # ^= tweak[]
2777         pxor    0x10(%rsp), @XMM[1]
2778         movdqu  @XMM[0], 0x00($out)     # write output
2779         movdqu  @XMM[1], 0x10($out)
2780         lea     0x20($out), $out
2781
2782         movdqa  0x20(%rsp), @XMM[7]     # next iteration tweak
2783         jmp     .Lxts_dec_done
2784 .align  16
2785 .Lxts_dec_1:
2786         pxor    @XMM[0], @XMM[8]
2787         lea     0x10($inp), $inp
2788         movdqa  @XMM[8], 0x20(%rbp)
2789         lea     0x20(%rbp), $arg1
2790         lea     0x20(%rbp), $arg2
2791         lea     ($key), $arg3
2792         call    asm_AES_decrypt         # doesn't touch %xmm
2793         pxor    0x20(%rbp), @XMM[0]     # ^= tweak[]
2794         #pxor   @XMM[8], @XMM[0]
2795         #lea    0x80(%rsp), %rax        # pass key schedule
2796         #mov    %edx, %r10d             # pass rounds
2797         #call   _bsaes_decrypt8
2798         #pxor   0x00(%rsp), @XMM[0]     # ^= tweak[]
2799         movdqu  @XMM[0], 0x00($out)     # write output
2800         lea     0x10($out), $out
2801
2802         movdqa  0x10(%rsp), @XMM[7]     # next iteration tweak
2803
2804 .Lxts_dec_done:
2805         and     \$15, %ebx
2806         jz      .Lxts_dec_ret
2807
2808         pxor    $twtmp, $twtmp
2809         movdqa  .Lxts_magic(%rip), $twmask
2810         pcmpgtd @XMM[7], $twtmp
2811         pshufd  \$0x13, $twtmp, $twres
2812         movdqa  @XMM[7], @XMM[6]
2813         paddq   @XMM[7], @XMM[7]        # psllq 1,$tweak
2814         pand    $twmask, $twres         # isolate carry and residue
2815         movdqu  ($inp), @XMM[0]
2816         pxor    $twres, @XMM[7]
2817
2818         lea     0x20(%rbp), $arg1
2819         pxor    @XMM[7], @XMM[0]
2820         lea     0x20(%rbp), $arg2
2821         movdqa  @XMM[0], 0x20(%rbp)
2822         lea     ($key), $arg3
2823         call    asm_AES_decrypt         # doesn't touch %xmm
2824         pxor    0x20(%rbp), @XMM[7]
2825         mov     $out, %rdx
2826         movdqu  @XMM[7], ($out)
2827
2828 .Lxts_dec_steal:
2829         movzb   16($inp), %eax
2830         movzb   (%rdx), %ecx
2831         lea     1($inp), $inp
2832         mov     %al, (%rdx)
2833         mov     %cl, 16(%rdx)
2834         lea     1(%rdx), %rdx
2835         sub     \$1,%ebx
2836         jnz     .Lxts_dec_steal
2837
2838         movdqu  ($out), @XMM[0]
2839         lea     0x20(%rbp), $arg1
2840         pxor    @XMM[6], @XMM[0]
2841         lea     0x20(%rbp), $arg2
2842         movdqa  @XMM[0], 0x20(%rbp)
2843         lea     ($key), $arg3
2844         call    asm_AES_decrypt         # doesn't touch %xmm
2845         pxor    0x20(%rbp), @XMM[6]
2846         movdqu  @XMM[6], ($out)
2847
2848 .Lxts_dec_ret:
2849         lea     (%rsp), %rax
2850         pxor    %xmm0, %xmm0
2851 .Lxts_dec_bzero:                        # wipe key schedule [if any]
2852         movdqa  %xmm0, 0x00(%rax)
2853         movdqa  %xmm0, 0x10(%rax)
2854         lea     0x20(%rax), %rax
2855         cmp     %rax, %rbp
2856         ja      .Lxts_dec_bzero
2857
2858         lea     0x78(%rbp),%rax
2859 ___
2860 $code.=<<___ if ($win64);
2861         movaps  0x40(%rbp), %xmm6
2862         movaps  0x50(%rbp), %xmm7
2863         movaps  0x60(%rbp), %xmm8
2864         movaps  0x70(%rbp), %xmm9
2865         movaps  0x80(%rbp), %xmm10
2866         movaps  0x90(%rbp), %xmm11
2867         movaps  0xa0(%rbp), %xmm12
2868         movaps  0xb0(%rbp), %xmm13
2869         movaps  0xc0(%rbp), %xmm14
2870         movaps  0xd0(%rbp), %xmm15
2871         lea     0xa0(%rax), %rax
2872 .Lxts_dec_tail:
2873 ___
2874 $code.=<<___;
2875         mov     -48(%rax), %r15
2876         mov     -40(%rax), %r14
2877         mov     -32(%rax), %r13
2878         mov     -24(%rax), %r12
2879         mov     -16(%rax), %rbx
2880         mov     -8(%rax), %rbp
2881         lea     (%rax), %rsp            # restore %rsp
2882 .Lxts_dec_epilogue:
2883         ret
2884 .size   bsaes_xts_decrypt,.-bsaes_xts_decrypt
2885 ___
2886 }
2887 $code.=<<___;
2888 .type   _bsaes_const,\@object
2889 .align  64
2890 _bsaes_const:
2891 .LM0ISR:        # InvShiftRows constants
2892         .quad   0x0a0e0206070b0f03, 0x0004080c0d010509
2893 .LISRM0:
2894         .quad   0x01040b0e0205080f, 0x0306090c00070a0d
2895 .LISR:
2896         .quad   0x0504070602010003, 0x0f0e0d0c080b0a09
2897 .LBS0:          # bit-slice constants
2898         .quad   0x5555555555555555, 0x5555555555555555
2899 .LBS1:
2900         .quad   0x3333333333333333, 0x3333333333333333
2901 .LBS2:
2902         .quad   0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f
2903 .LSR:           # shiftrows constants
2904         .quad   0x0504070600030201, 0x0f0e0d0c0a09080b
2905 .LSRM0:
2906         .quad   0x0304090e00050a0f, 0x01060b0c0207080d
2907 .LM0SR:
2908         .quad   0x0a0e02060f03070b, 0x0004080c05090d01
2909 .LSWPUP:        # byte-swap upper dword
2910         .quad   0x0706050403020100, 0x0c0d0e0f0b0a0908
2911 .LSWPUPM0SR:
2912         .quad   0x0a0d02060c03070b, 0x0004080f05090e01
2913 .LADD1:         # counter increment constants
2914         .quad   0x0000000000000000, 0x0000000100000000
2915 .LADD2:
2916         .quad   0x0000000000000000, 0x0000000200000000
2917 .LADD3:
2918         .quad   0x0000000000000000, 0x0000000300000000
2919 .LADD4:
2920         .quad   0x0000000000000000, 0x0000000400000000
2921 .LADD5:
2922         .quad   0x0000000000000000, 0x0000000500000000
2923 .LADD6:
2924         .quad   0x0000000000000000, 0x0000000600000000
2925 .LADD7:
2926         .quad   0x0000000000000000, 0x0000000700000000
2927 .LADD8:
2928         .quad   0x0000000000000000, 0x0000000800000000
2929 .Lxts_magic:
2930         .long   0x87,0,1,0
2931 .Lmasks:
2932         .quad   0x0101010101010101, 0x0101010101010101
2933         .quad   0x0202020202020202, 0x0202020202020202
2934         .quad   0x0404040404040404, 0x0404040404040404
2935         .quad   0x0808080808080808, 0x0808080808080808
2936 .LM0:
2937         .quad   0x02060a0e03070b0f, 0x0004080c0105090d
2938 .L63:
2939         .quad   0x6363636363636363, 0x6363636363636363
2940 .asciz  "Bit-sliced AES for x86_64/SSSE3, Emilia Käsper, Peter Schwabe, Andy Polyakov"
2941 .align  64
2942 .size   _bsaes_const,.-_bsaes_const
2943 ___
2944
2945 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
2946 #               CONTEXT *context,DISPATCHER_CONTEXT *disp)
2947 if ($win64) {
2948 $rec="%rcx";
2949 $frame="%rdx";
2950 $context="%r8";
2951 $disp="%r9";
2952
2953 $code.=<<___;
2954 .extern __imp_RtlVirtualUnwind
2955 .type   se_handler,\@abi-omnipotent
2956 .align  16
2957 se_handler:
2958         push    %rsi
2959         push    %rdi
2960         push    %rbx
2961         push    %rbp
2962         push    %r12
2963         push    %r13
2964         push    %r14
2965         push    %r15
2966         pushfq
2967         sub     \$64,%rsp
2968
2969         mov     120($context),%rax      # pull context->Rax
2970         mov     248($context),%rbx      # pull context->Rip
2971
2972         mov     8($disp),%rsi           # disp->ImageBase
2973         mov     56($disp),%r11          # disp->HandlerData
2974
2975         mov     0(%r11),%r10d           # HandlerData[0]
2976         lea     (%rsi,%r10),%r10        # prologue label
2977         cmp     %r10,%rbx               # context->Rip<=prologue label
2978         jbe     .Lin_prologue
2979
2980         mov     4(%r11),%r10d           # HandlerData[1]
2981         lea     (%rsi,%r10),%r10        # epilogue label
2982         cmp     %r10,%rbx               # context->Rip>=epilogue label
2983         jae     .Lin_prologue
2984
2985         mov     8(%r11),%r10d           # HandlerData[2]
2986         lea     (%rsi,%r10),%r10        # epilogue label
2987         cmp     %r10,%rbx               # context->Rip>=tail label
2988         jae     .Lin_tail
2989
2990         mov     160($context),%rax      # pull context->Rbp
2991
2992         lea     0x40(%rax),%rsi         # %xmm save area
2993         lea     512($context),%rdi      # &context.Xmm6
2994         mov     \$20,%ecx               # 10*sizeof(%xmm0)/sizeof(%rax)
2995         .long   0xa548f3fc              # cld; rep movsq
2996         lea     0xa0+0x78(%rax),%rax    # adjust stack pointer
2997
2998 .Lin_tail:
2999         mov     -48(%rax),%rbp
3000         mov     -40(%rax),%rbx
3001         mov     -32(%rax),%r12
3002         mov     -24(%rax),%r13
3003         mov     -16(%rax),%r14
3004         mov     -8(%rax),%r15
3005         mov     %rbx,144($context)      # restore context->Rbx
3006         mov     %rbp,160($context)      # restore context->Rbp
3007         mov     %r12,216($context)      # restore context->R12
3008         mov     %r13,224($context)      # restore context->R13
3009         mov     %r14,232($context)      # restore context->R14
3010         mov     %r15,240($context)      # restore context->R15
3011
3012 .Lin_prologue:
3013         mov     %rax,152($context)      # restore context->Rsp
3014
3015         mov     40($disp),%rdi          # disp->ContextRecord
3016         mov     $context,%rsi           # context
3017         mov     \$`1232/8`,%ecx         # sizeof(CONTEXT)
3018         .long   0xa548f3fc              # cld; rep movsq
3019
3020         mov     $disp,%rsi
3021         xor     %rcx,%rcx               # arg1, UNW_FLAG_NHANDLER
3022         mov     8(%rsi),%rdx            # arg2, disp->ImageBase
3023         mov     0(%rsi),%r8             # arg3, disp->ControlPc
3024         mov     16(%rsi),%r9            # arg4, disp->FunctionEntry
3025         mov     40(%rsi),%r10           # disp->ContextRecord
3026         lea     56(%rsi),%r11           # &disp->HandlerData
3027         lea     24(%rsi),%r12           # &disp->EstablisherFrame
3028         mov     %r10,32(%rsp)           # arg5
3029         mov     %r11,40(%rsp)           # arg6
3030         mov     %r12,48(%rsp)           # arg7
3031         mov     %rcx,56(%rsp)           # arg8, (NULL)
3032         call    *__imp_RtlVirtualUnwind(%rip)
3033
3034         mov     \$1,%eax                # ExceptionContinueSearch
3035         add     \$64,%rsp
3036         popfq
3037         pop     %r15
3038         pop     %r14
3039         pop     %r13
3040         pop     %r12
3041         pop     %rbp
3042         pop     %rbx
3043         pop     %rdi
3044         pop     %rsi
3045         ret
3046 .size   se_handler,.-se_handler
3047
3048 .section        .pdata
3049 .align  4
3050 ___
3051 $code.=<<___ if ($ecb);
3052         .rva    .Lecb_enc_prologue
3053         .rva    .Lecb_enc_epilogue
3054         .rva    .Lecb_enc_info
3055
3056         .rva    .Lecb_dec_prologue
3057         .rva    .Lecb_dec_epilogue
3058         .rva    .Lecb_dec_info
3059 ___
3060 $code.=<<___;
3061         .rva    .Lcbc_dec_prologue
3062         .rva    .Lcbc_dec_epilogue
3063         .rva    .Lcbc_dec_info
3064
3065         .rva    .Lctr_enc_prologue
3066         .rva    .Lctr_enc_epilogue
3067         .rva    .Lctr_enc_info
3068
3069         .rva    .Lxts_enc_prologue
3070         .rva    .Lxts_enc_epilogue
3071         .rva    .Lxts_enc_info
3072
3073         .rva    .Lxts_dec_prologue
3074         .rva    .Lxts_dec_epilogue
3075         .rva    .Lxts_dec_info
3076
3077 .section        .xdata
3078 .align  8
3079 ___
3080 $code.=<<___ if ($ecb);
3081 .Lecb_enc_info:
3082         .byte   9,0,0,0
3083         .rva    se_handler
3084         .rva    .Lecb_enc_body,.Lecb_enc_epilogue       # HandlerData[]
3085         .rva    .Lecb_enc_tail
3086         .long   0
3087 .Lecb_dec_info:
3088         .byte   9,0,0,0
3089         .rva    se_handler
3090         .rva    .Lecb_dec_body,.Lecb_dec_epilogue       # HandlerData[]
3091         .rva    .Lecb_dec_tail
3092         .long   0
3093 ___
3094 $code.=<<___;
3095 .Lcbc_dec_info:
3096         .byte   9,0,0,0
3097         .rva    se_handler
3098         .rva    .Lcbc_dec_body,.Lcbc_dec_epilogue       # HandlerData[]
3099         .rva    .Lcbc_dec_tail
3100         .long   0
3101 .Lctr_enc_info:
3102         .byte   9,0,0,0
3103         .rva    se_handler
3104         .rva    .Lctr_enc_body,.Lctr_enc_epilogue       # HandlerData[]
3105         .rva    .Lctr_enc_tail
3106         .long   0
3107 .Lxts_enc_info:
3108         .byte   9,0,0,0
3109         .rva    se_handler
3110         .rva    .Lxts_enc_body,.Lxts_enc_epilogue       # HandlerData[]
3111         .rva    .Lxts_enc_tail
3112         .long   0
3113 .Lxts_dec_info:
3114         .byte   9,0,0,0
3115         .rva    se_handler
3116         .rva    .Lxts_dec_body,.Lxts_dec_epilogue       # HandlerData[]
3117         .rva    .Lxts_dec_tail
3118         .long   0
3119 ___
3120 }
3121
3122 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
3123
3124 print $code;
3125
3126 close STDOUT;