1#! /usr/bin/env perl
2# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
3#
4# Licensed under the Apache License 2.0 (the "License").  You may not use
5# this file except in compliance with the License.  You can obtain a copy
6# in the file LICENSE in the source distribution or at
7# https://www.openssl.org/source/license.html
8
9#
10# ====================================================================
11# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
12# project. The module is, however, dual licensed under OpenSSL and
13# CRYPTOGAMS licenses depending on where you obtain it. For further
14# details see http://www.openssl.org/~appro/cryptogams/.
15# ====================================================================
16#
17# This module implements support for Intel AES-NI extension. In
18# OpenSSL context it's used with Intel engine, but can also be used as
19# drop-in replacement for crypto/aes/asm/aes-x86_64.pl [see below for
20# details].
21#
22# Performance.
23#
24# Given aes(enc|dec) instructions' latency asymptotic performance for
25# non-parallelizable modes such as CBC encrypt is 3.75 cycles per byte
26# processed with 128-bit key. And given their throughput asymptotic
27# performance for parallelizable modes is 1.25 cycles per byte. Being
28# asymptotic limit it's not something you commonly achieve in reality,
29# but how close does one get? Below are results collected for
30# different modes and block sized. Pairs of numbers are for en-/
31# decryption.
32#
33#	16-byte     64-byte     256-byte    1-KB        8-KB
34# ECB	4.25/4.25   1.38/1.38   1.28/1.28   1.26/1.26	1.26/1.26
35# CTR	5.42/5.42   1.92/1.92   1.44/1.44   1.28/1.28   1.26/1.26
36# CBC	4.38/4.43   4.15/1.43   4.07/1.32   4.07/1.29   4.06/1.28
37# CCM	5.66/9.42   4.42/5.41   4.16/4.40   4.09/4.15   4.06/4.07
38# OFB	5.42/5.42   4.64/4.64   4.44/4.44   4.39/4.39   4.38/4.38
39# CFB	5.73/5.85   5.56/5.62   5.48/5.56   5.47/5.55   5.47/5.55
40#
41# ECB, CTR, CBC and CCM results are free from EVP overhead. This means
42# that otherwise used 'openssl speed -evp aes-128-??? -engine aesni
43# [-decrypt]' will exhibit 10-15% worse results for smaller blocks.
44# The results were collected with specially crafted speed.c benchmark
45# in order to compare them with results reported in "Intel Advanced
46# Encryption Standard (AES) New Instruction Set" White Paper Revision
47# 3.0 dated May 2010. All above results are consistently better. This
48# module also provides better performance for block sizes smaller than
49# 128 bytes in points *not* represented in the above table.
50#
51# Looking at the results for 8-KB buffer.
52#
53# CFB and OFB results are far from the limit, because implementation
54# uses "generic" CRYPTO_[c|o]fb128_encrypt interfaces relying on
55# single-block aesni_encrypt, which is not the most optimal way to go.
56# CBC encrypt result is unexpectedly high and there is no documented
57# explanation for it. Seemingly there is a small penalty for feeding
58# the result back to AES unit the way it's done in CBC mode. There is
59# nothing one can do and the result appears optimal. CCM result is
60# identical to CBC, because CBC-MAC is essentially CBC encrypt without
61# saving output. CCM CTR "stays invisible," because it's neatly
62# interleaved with CBC-MAC. This provides ~30% improvement over
63# "straightforward" CCM implementation with CTR and CBC-MAC performed
64# disjointly. Parallelizable modes practically achieve the theoretical
65# limit.
66#
67# Looking at how results vary with buffer size.
68#
69# Curves are practically saturated at 1-KB buffer size. In most cases
70# "256-byte" performance is >95%, and "64-byte" is ~90% of "8-KB" one.
71# CTR curve doesn't follow this pattern and is "slowest" changing one
72# with "256-byte" result being 87% of "8-KB." This is because overhead
73# in CTR mode is most computationally intensive. Small-block CCM
74# decrypt is slower than encrypt, because first CTR and last CBC-MAC
75# iterations can't be interleaved.
76#
77# Results for 192- and 256-bit keys.
78#
79# EVP-free results were observed to scale perfectly with number of
80# rounds for larger block sizes, i.e. 192-bit result being 10/12 times
81# lower and 256-bit one - 10/14. Well, in CBC encrypt case differences
82# are a tad smaller, because the above mentioned penalty biases all
83# results by same constant value. In similar way function call
84# overhead affects small-block performance, as well as OFB and CFB
85# results. Differences are not large, most common coefficients are
86# 10/11.7 and 10/13.4 (as opposite to 10/12.0 and 10/14.0), but one
87# observe even 10/11.2 and 10/12.4 (CTR, OFB, CFB)...
88
89# January 2011
90#
91# While Westmere processor features 6 cycles latency for aes[enc|dec]
92# instructions, which can be scheduled every second cycle, Sandy
93# Bridge spends 8 cycles per instruction, but it can schedule them
94# every cycle. This means that code targeting Westmere would perform
95# suboptimally on Sandy Bridge. Therefore this update.
96#
97# In addition, non-parallelizable CBC encrypt (as well as CCM) is
98# optimized. Relative improvement might appear modest, 8% on Westmere,
99# but in absolute terms it's 3.77 cycles per byte encrypted with
100# 128-bit key on Westmere, and 5.07 - on Sandy Bridge. These numbers
101# should be compared to asymptotic limits of 3.75 for Westmere and
102# 5.00 for Sandy Bridge. Actually, the fact that they get this close
103# to asymptotic limits is quite amazing. Indeed, the limit is
104# calculated as latency times number of rounds, 10 for 128-bit key,
105# and divided by 16, the number of bytes in block, or in other words
106# it accounts *solely* for aesenc instructions. But there are extra
107# instructions, and numbers so close to the asymptotic limits mean
108# that it's as if it takes as little as *one* additional cycle to
109# execute all of them. How is it possible? It is possible thanks to
110# out-of-order execution logic, which manages to overlap post-
111# processing of previous block, things like saving the output, with
112# actual encryption of current block, as well as pre-processing of
113# current block, things like fetching input and xor-ing it with
114# 0-round element of the key schedule, with actual encryption of
115# previous block. Keep this in mind...
116#
117# For parallelizable modes, such as ECB, CBC decrypt, CTR, higher
118# performance is achieved by interleaving instructions working on
119# independent blocks. In which case asymptotic limit for such modes
120# can be obtained by dividing above mentioned numbers by AES
121# instructions' interleave factor. Westmere can execute at most 3
122# instructions at a time, meaning that optimal interleave factor is 3,
123# and that's where the "magic" number of 1.25 come from. "Optimal
124# interleave factor" means that increase of interleave factor does
125# not improve performance. The formula has proven to reflect reality
126# pretty well on Westmere... Sandy Bridge on the other hand can
127# execute up to 8 AES instructions at a time, so how does varying
128# interleave factor affect the performance? Here is table for ECB
129# (numbers are cycles per byte processed with 128-bit key):
130#
131# instruction interleave factor		3x	6x	8x
132# theoretical asymptotic limit		1.67	0.83	0.625
133# measured performance for 8KB block	1.05	0.86	0.84
134#
135# "as if" interleave factor		4.7x	5.8x	6.0x
136#
137# Further data for other parallelizable modes:
138#
139# CBC decrypt				1.16	0.93	0.74
140# CTR					1.14	0.91	0.74
141#
142# Well, given 3x column it's probably inappropriate to call the limit
143# asymptotic, if it can be surpassed, isn't it? What happens there?
144# Rewind to CBC paragraph for the answer. Yes, out-of-order execution
145# magic is responsible for this. Processor overlaps not only the
146# additional instructions with AES ones, but even AES instructions
147# processing adjacent triplets of independent blocks. In the 6x case
148# additional instructions  still claim disproportionally small amount
149# of additional cycles, but in 8x case number of instructions must be
150# a tad too high for out-of-order logic to cope with, and AES unit
151# remains underutilized... As you can see 8x interleave is hardly
152# justifiable, so there no need to feel bad that 32-bit aesni-x86.pl
153# utilizes 6x interleave because of limited register bank capacity.
154#
155# Higher interleave factors do have negative impact on Westmere
156# performance. While for ECB mode it's negligible ~1.5%, other
157# parallelizables perform ~5% worse, which is outweighed by ~25%
158# improvement on Sandy Bridge. To balance regression on Westmere
159# CTR mode was implemented with 6x aesenc interleave factor.
160
161# April 2011
162#
163# Add aesni_xts_[en|de]crypt. Westmere spends 1.25 cycles processing
164# one byte out of 8KB with 128-bit key, Sandy Bridge - 0.90. Just like
165# in CTR mode AES instruction interleave factor was chosen to be 6x.
166
167# November 2015
168#
169# Add aesni_ocb_[en|de]crypt. AES instruction interleave factor was
170# chosen to be 6x.
171
172######################################################################
173# Current large-block performance in cycles per byte processed with
174# 128-bit key (less is better).
175#
176#		CBC en-/decrypt	CTR	XTS	ECB	OCB
177# Westmere	3.77/1.25	1.25	1.25	1.26
178# * Bridge	5.07/0.74	0.75	0.90	0.85	0.98
179# Haswell	4.44/0.63	0.63	0.73	0.63	0.70
180# Skylake	2.62/0.63	0.63	0.63	0.63
181# Silvermont	5.75/3.54	3.56	4.12	3.87(*)	4.11
182# Knights L	2.54/0.77	0.78	0.85	-	1.50
183# Goldmont	3.82/1.26	1.26	1.29	1.29	1.50
184# Bulldozer	5.77/0.70	0.72	0.90	0.70	0.95
185# Ryzen		2.71/0.35	0.35	0.44	0.38	0.49
186#
187# (*)	Atom Silvermont ECB result is suboptimal because of penalties
188#	incurred by operations on %xmm8-15. As ECB is not considered
189#	critical, nothing was done to mitigate the problem.
190
191$PREFIX="aesni";	# if $PREFIX is set to "AES", the script
192			# generates drop-in replacement for
193			# crypto/aes/asm/aes-x86_64.pl:-)
194
195# $output is the last argument if it looks like a file (it has an extension)
196# $flavour is the first argument if it doesn't look like a file
197$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
198$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
199
200$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
201
202$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
203( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
204( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
205die "can't locate x86_64-xlate.pl";
206
207open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
208    or die "can't call $xlate: $!";
209*STDOUT=*OUT;
210
211$movkey = $PREFIX eq "aesni" ? "movups" : "movups";
212@_4args=$win64?	("%rcx","%rdx","%r8", "%r9") :	# Win64 order
213		("%rdi","%rsi","%rdx","%rcx");	# Unix order
214
215$code=".text\n";
216$code.=".extern	OPENSSL_ia32cap_P\n";
217
218$rounds="%eax";	# input to and changed by aesni_[en|de]cryptN !!!
219# this is natural Unix argument order for public $PREFIX_[ecb|cbc]_encrypt ...
220$inp="%rdi";
221$out="%rsi";
222$len="%rdx";
223$key="%rcx";	# input to and changed by aesni_[en|de]cryptN !!!
224$ivp="%r8";	# cbc, ctr, ...
225
226$rnds_="%r10d";	# backup copy for $rounds
227$key_="%r11";	# backup copy for $key
228
229# %xmm register layout
230$rndkey0="%xmm0";	$rndkey1="%xmm1";
231$inout0="%xmm2";	$inout1="%xmm3";
232$inout2="%xmm4";	$inout3="%xmm5";
233$inout4="%xmm6";	$inout5="%xmm7";
234$inout6="%xmm8";	$inout7="%xmm9";
235
236$in2="%xmm6";		$in1="%xmm7";	# used in CBC decrypt, CTR, ...
237$in0="%xmm8";		$iv="%xmm9";
238
239# Inline version of internal aesni_[en|de]crypt1.
240#
241# Why folded loop? Because aes[enc|dec] is slow enough to accommodate
242# cycles which take care of loop variables...
243{ my $sn;
244sub aesni_generate1 {
245my ($p,$key,$rounds,$inout,$ivec)=@_;	$inout=$inout0 if (!defined($inout));
246++$sn;
247$code.=<<___;
248	$movkey	($key),$rndkey0
249	$movkey	16($key),$rndkey1
250___
251$code.=<<___ if (defined($ivec));
252	xorps	$rndkey0,$ivec
253	lea	32($key),$key
254	xorps	$ivec,$inout
255___
256$code.=<<___ if (!defined($ivec));
257	lea	32($key),$key
258	xorps	$rndkey0,$inout
259___
260$code.=<<___;
261.Loop_${p}1_$sn:
262	aes${p}	$rndkey1,$inout
263	dec	$rounds
264	$movkey	($key),$rndkey1
265	lea	16($key),$key
266	jnz	.Loop_${p}1_$sn	# loop body is 16 bytes
267	aes${p}last	$rndkey1,$inout
268___
269}}
270# void $PREFIX_[en|de]crypt (const void *inp,void *out,const AES_KEY *key);
271#
272{ my ($inp,$out,$key) = @_4args;
273
274$code.=<<___;
275.globl	${PREFIX}_encrypt
276.type	${PREFIX}_encrypt,\@abi-omnipotent
277.align	16
278${PREFIX}_encrypt:
279.cfi_startproc
280	endbranch
281	movups	($inp),$inout0		# load input
282	mov	240($key),$rounds	# key->rounds
283___
284	&aesni_generate1("enc",$key,$rounds);
285$code.=<<___;
286	 pxor	$rndkey0,$rndkey0	# clear register bank
287	 pxor	$rndkey1,$rndkey1
288	movups	$inout0,($out)		# output
289	 pxor	$inout0,$inout0
290	ret
291.cfi_endproc
292.size	${PREFIX}_encrypt,.-${PREFIX}_encrypt
293
294.globl	${PREFIX}_decrypt
295.type	${PREFIX}_decrypt,\@abi-omnipotent
296.align	16
297${PREFIX}_decrypt:
298.cfi_startproc
299	endbranch
300	movups	($inp),$inout0		# load input
301	mov	240($key),$rounds	# key->rounds
302___
303	&aesni_generate1("dec",$key,$rounds);
304$code.=<<___;
305	 pxor	$rndkey0,$rndkey0	# clear register bank
306	 pxor	$rndkey1,$rndkey1
307	movups	$inout0,($out)		# output
308	 pxor	$inout0,$inout0
309	ret
310.cfi_endproc
311.size	${PREFIX}_decrypt, .-${PREFIX}_decrypt
312___
313}
314
315# _aesni_[en|de]cryptN are private interfaces, N denotes interleave
316# factor. Why 3x subroutine were originally used in loops? Even though
317# aes[enc|dec] latency was originally 6, it could be scheduled only
318# every *2nd* cycle. Thus 3x interleave was the one providing optimal
319# utilization, i.e. when subroutine's throughput is virtually same as
320# of non-interleaved subroutine [for number of input blocks up to 3].
321# This is why it originally made no sense to implement 2x subroutine.
322# But times change and it became appropriate to spend extra 192 bytes
323# on 2x subroutine on Atom Silvermont account. For processors that
324# can schedule aes[enc|dec] every cycle optimal interleave factor
325# equals to corresponding instructions latency. 8x is optimal for
326# * Bridge and "super-optimal" for other Intel CPUs...
327
328sub aesni_generate2 {
329my $dir=shift;
330# As already mentioned it takes in $key and $rounds, which are *not*
331# preserved. $inout[0-1] is cipher/clear text...
332$code.=<<___;
333.type	_aesni_${dir}rypt2,\@abi-omnipotent
334.align	16
335_aesni_${dir}rypt2:
336.cfi_startproc
337	$movkey	($key),$rndkey0
338	shl	\$4,$rounds
339	$movkey	16($key),$rndkey1
340	xorps	$rndkey0,$inout0
341	xorps	$rndkey0,$inout1
342	$movkey	32($key),$rndkey0
343	lea	32($key,$rounds),$key
344	neg	%rax				# $rounds
345	add	\$16,%rax
346
347.L${dir}_loop2:
348	aes${dir}	$rndkey1,$inout0
349	aes${dir}	$rndkey1,$inout1
350	$movkey		($key,%rax),$rndkey1
351	add		\$32,%rax
352	aes${dir}	$rndkey0,$inout0
353	aes${dir}	$rndkey0,$inout1
354	$movkey		-16($key,%rax),$rndkey0
355	jnz		.L${dir}_loop2
356
357	aes${dir}	$rndkey1,$inout0
358	aes${dir}	$rndkey1,$inout1
359	aes${dir}last	$rndkey0,$inout0
360	aes${dir}last	$rndkey0,$inout1
361	ret
362.cfi_endproc
363.size	_aesni_${dir}rypt2,.-_aesni_${dir}rypt2
364___
365}
366sub aesni_generate3 {
367my $dir=shift;
368# As already mentioned it takes in $key and $rounds, which are *not*
369# preserved. $inout[0-2] is cipher/clear text...
370$code.=<<___;
371.type	_aesni_${dir}rypt3,\@abi-omnipotent
372.align	16
373_aesni_${dir}rypt3:
374.cfi_startproc
375	$movkey	($key),$rndkey0
376	shl	\$4,$rounds
377	$movkey	16($key),$rndkey1
378	xorps	$rndkey0,$inout0
379	xorps	$rndkey0,$inout1
380	xorps	$rndkey0,$inout2
381	$movkey	32($key),$rndkey0
382	lea	32($key,$rounds),$key
383	neg	%rax				# $rounds
384	add	\$16,%rax
385
386.L${dir}_loop3:
387	aes${dir}	$rndkey1,$inout0
388	aes${dir}	$rndkey1,$inout1
389	aes${dir}	$rndkey1,$inout2
390	$movkey		($key,%rax),$rndkey1
391	add		\$32,%rax
392	aes${dir}	$rndkey0,$inout0
393	aes${dir}	$rndkey0,$inout1
394	aes${dir}	$rndkey0,$inout2
395	$movkey		-16($key,%rax),$rndkey0
396	jnz		.L${dir}_loop3
397
398	aes${dir}	$rndkey1,$inout0
399	aes${dir}	$rndkey1,$inout1
400	aes${dir}	$rndkey1,$inout2
401	aes${dir}last	$rndkey0,$inout0
402	aes${dir}last	$rndkey0,$inout1
403	aes${dir}last	$rndkey0,$inout2
404	ret
405.cfi_endproc
406.size	_aesni_${dir}rypt3,.-_aesni_${dir}rypt3
407___
408}
409# 4x interleave is implemented to improve small block performance,
410# most notably [and naturally] 4 block by ~30%. One can argue that one
411# should have implemented 5x as well, but improvement would be <20%,
412# so it's not worth it...
413sub aesni_generate4 {
414my $dir=shift;
415# As already mentioned it takes in $key and $rounds, which are *not*
416# preserved. $inout[0-3] is cipher/clear text...
417$code.=<<___;
418.type	_aesni_${dir}rypt4,\@abi-omnipotent
419.align	16
420_aesni_${dir}rypt4:
421.cfi_startproc
422	$movkey	($key),$rndkey0
423	shl	\$4,$rounds
424	$movkey	16($key),$rndkey1
425	xorps	$rndkey0,$inout0
426	xorps	$rndkey0,$inout1
427	xorps	$rndkey0,$inout2
428	xorps	$rndkey0,$inout3
429	$movkey	32($key),$rndkey0
430	lea	32($key,$rounds),$key
431	neg	%rax				# $rounds
432	.byte	0x0f,0x1f,0x00
433	add	\$16,%rax
434
435.L${dir}_loop4:
436	aes${dir}	$rndkey1,$inout0
437	aes${dir}	$rndkey1,$inout1
438	aes${dir}	$rndkey1,$inout2
439	aes${dir}	$rndkey1,$inout3
440	$movkey		($key,%rax),$rndkey1
441	add		\$32,%rax
442	aes${dir}	$rndkey0,$inout0
443	aes${dir}	$rndkey0,$inout1
444	aes${dir}	$rndkey0,$inout2
445	aes${dir}	$rndkey0,$inout3
446	$movkey		-16($key,%rax),$rndkey0
447	jnz		.L${dir}_loop4
448
449	aes${dir}	$rndkey1,$inout0
450	aes${dir}	$rndkey1,$inout1
451	aes${dir}	$rndkey1,$inout2
452	aes${dir}	$rndkey1,$inout3
453	aes${dir}last	$rndkey0,$inout0
454	aes${dir}last	$rndkey0,$inout1
455	aes${dir}last	$rndkey0,$inout2
456	aes${dir}last	$rndkey0,$inout3
457	ret
458.cfi_endproc
459.size	_aesni_${dir}rypt4,.-_aesni_${dir}rypt4
460___
461}
462sub aesni_generate6 {
463my $dir=shift;
464# As already mentioned it takes in $key and $rounds, which are *not*
465# preserved. $inout[0-5] is cipher/clear text...
466$code.=<<___;
467.type	_aesni_${dir}rypt6,\@abi-omnipotent
468.align	16
469_aesni_${dir}rypt6:
470.cfi_startproc
471	$movkey		($key),$rndkey0
472	shl		\$4,$rounds
473	$movkey		16($key),$rndkey1
474	xorps		$rndkey0,$inout0
475	pxor		$rndkey0,$inout1
476	pxor		$rndkey0,$inout2
477	aes${dir}	$rndkey1,$inout0
478	lea		32($key,$rounds),$key
479	neg		%rax			# $rounds
480	aes${dir}	$rndkey1,$inout1
481	pxor		$rndkey0,$inout3
482	pxor		$rndkey0,$inout4
483	aes${dir}	$rndkey1,$inout2
484	pxor		$rndkey0,$inout5
485	$movkey		($key,%rax),$rndkey0
486	add		\$16,%rax
487	jmp		.L${dir}_loop6_enter
488.align	16
489.L${dir}_loop6:
490	aes${dir}	$rndkey1,$inout0
491	aes${dir}	$rndkey1,$inout1
492	aes${dir}	$rndkey1,$inout2
493.L${dir}_loop6_enter:
494	aes${dir}	$rndkey1,$inout3
495	aes${dir}	$rndkey1,$inout4
496	aes${dir}	$rndkey1,$inout5
497	$movkey		($key,%rax),$rndkey1
498	add		\$32,%rax
499	aes${dir}	$rndkey0,$inout0
500	aes${dir}	$rndkey0,$inout1
501	aes${dir}	$rndkey0,$inout2
502	aes${dir}	$rndkey0,$inout3
503	aes${dir}	$rndkey0,$inout4
504	aes${dir}	$rndkey0,$inout5
505	$movkey		-16($key,%rax),$rndkey0
506	jnz		.L${dir}_loop6
507
508	aes${dir}	$rndkey1,$inout0
509	aes${dir}	$rndkey1,$inout1
510	aes${dir}	$rndkey1,$inout2
511	aes${dir}	$rndkey1,$inout3
512	aes${dir}	$rndkey1,$inout4
513	aes${dir}	$rndkey1,$inout5
514	aes${dir}last	$rndkey0,$inout0
515	aes${dir}last	$rndkey0,$inout1
516	aes${dir}last	$rndkey0,$inout2
517	aes${dir}last	$rndkey0,$inout3
518	aes${dir}last	$rndkey0,$inout4
519	aes${dir}last	$rndkey0,$inout5
520	ret
521.cfi_endproc
522.size	_aesni_${dir}rypt6,.-_aesni_${dir}rypt6
523___
524}
525sub aesni_generate8 {
526my $dir=shift;
527# As already mentioned it takes in $key and $rounds, which are *not*
528# preserved. $inout[0-7] is cipher/clear text...
529$code.=<<___;
530.type	_aesni_${dir}rypt8,\@abi-omnipotent
531.align	16
532_aesni_${dir}rypt8:
533.cfi_startproc
534	$movkey		($key),$rndkey0
535	shl		\$4,$rounds
536	$movkey		16($key),$rndkey1
537	xorps		$rndkey0,$inout0
538	xorps		$rndkey0,$inout1
539	pxor		$rndkey0,$inout2
540	pxor		$rndkey0,$inout3
541	pxor		$rndkey0,$inout4
542	lea		32($key,$rounds),$key
543	neg		%rax			# $rounds
544	aes${dir}	$rndkey1,$inout0
545	pxor		$rndkey0,$inout5
546	pxor		$rndkey0,$inout6
547	aes${dir}	$rndkey1,$inout1
548	pxor		$rndkey0,$inout7
549	$movkey		($key,%rax),$rndkey0
550	add		\$16,%rax
551	jmp		.L${dir}_loop8_inner
552.align	16
553.L${dir}_loop8:
554	aes${dir}	$rndkey1,$inout0
555	aes${dir}	$rndkey1,$inout1
556.L${dir}_loop8_inner:
557	aes${dir}	$rndkey1,$inout2
558	aes${dir}	$rndkey1,$inout3
559	aes${dir}	$rndkey1,$inout4
560	aes${dir}	$rndkey1,$inout5
561	aes${dir}	$rndkey1,$inout6
562	aes${dir}	$rndkey1,$inout7
563.L${dir}_loop8_enter:
564	$movkey		($key,%rax),$rndkey1
565	add		\$32,%rax
566	aes${dir}	$rndkey0,$inout0
567	aes${dir}	$rndkey0,$inout1
568	aes${dir}	$rndkey0,$inout2
569	aes${dir}	$rndkey0,$inout3
570	aes${dir}	$rndkey0,$inout4
571	aes${dir}	$rndkey0,$inout5
572	aes${dir}	$rndkey0,$inout6
573	aes${dir}	$rndkey0,$inout7
574	$movkey		-16($key,%rax),$rndkey0
575	jnz		.L${dir}_loop8
576
577	aes${dir}	$rndkey1,$inout0
578	aes${dir}	$rndkey1,$inout1
579	aes${dir}	$rndkey1,$inout2
580	aes${dir}	$rndkey1,$inout3
581	aes${dir}	$rndkey1,$inout4
582	aes${dir}	$rndkey1,$inout5
583	aes${dir}	$rndkey1,$inout6
584	aes${dir}	$rndkey1,$inout7
585	aes${dir}last	$rndkey0,$inout0
586	aes${dir}last	$rndkey0,$inout1
587	aes${dir}last	$rndkey0,$inout2
588	aes${dir}last	$rndkey0,$inout3
589	aes${dir}last	$rndkey0,$inout4
590	aes${dir}last	$rndkey0,$inout5
591	aes${dir}last	$rndkey0,$inout6
592	aes${dir}last	$rndkey0,$inout7
593	ret
594.cfi_endproc
595.size	_aesni_${dir}rypt8,.-_aesni_${dir}rypt8
596___
597}
598&aesni_generate2("enc") if ($PREFIX eq "aesni");
599&aesni_generate2("dec");
600&aesni_generate3("enc") if ($PREFIX eq "aesni");
601&aesni_generate3("dec");
602&aesni_generate4("enc") if ($PREFIX eq "aesni");
603&aesni_generate4("dec");
604&aesni_generate6("enc") if ($PREFIX eq "aesni");
605&aesni_generate6("dec");
606&aesni_generate8("enc") if ($PREFIX eq "aesni");
607&aesni_generate8("dec");
608
609if ($PREFIX eq "aesni") {
610########################################################################
611# void aesni_ecb_encrypt (const void *in, void *out,
612#			  size_t length, const AES_KEY *key,
613#			  int enc);
614$code.=<<___;
615.globl	aesni_ecb_encrypt
616.type	aesni_ecb_encrypt,\@function,5
617.align	16
618aesni_ecb_encrypt:
619.cfi_startproc
620	endbranch
621___
622$code.=<<___ if ($win64);
623	lea	-0x58(%rsp),%rsp
624	movaps	%xmm6,(%rsp)		# offload $inout4..7
625	movaps	%xmm7,0x10(%rsp)
626	movaps	%xmm8,0x20(%rsp)
627	movaps	%xmm9,0x30(%rsp)
628.Lecb_enc_body:
629___
630$code.=<<___;
631	and	\$-16,$len		# if ($len<16)
632	jz	.Lecb_ret		# return
633
634	mov	240($key),$rounds	# key->rounds
635	$movkey	($key),$rndkey0
636	mov	$key,$key_		# backup $key
637	mov	$rounds,$rnds_		# backup $rounds
638	test	%r8d,%r8d		# 5th argument
639	jz	.Lecb_decrypt
640#--------------------------- ECB ENCRYPT ------------------------------#
641	cmp	\$0x80,$len		# if ($len<8*16)
642	jb	.Lecb_enc_tail		# short input
643
644	movdqu	($inp),$inout0		# load 8 input blocks
645	movdqu	0x10($inp),$inout1
646	movdqu	0x20($inp),$inout2
647	movdqu	0x30($inp),$inout3
648	movdqu	0x40($inp),$inout4
649	movdqu	0x50($inp),$inout5
650	movdqu	0x60($inp),$inout6
651	movdqu	0x70($inp),$inout7
652	lea	0x80($inp),$inp		# $inp+=8*16
653	sub	\$0x80,$len		# $len-=8*16 (can be zero)
654	jmp	.Lecb_enc_loop8_enter
655.align 16
656.Lecb_enc_loop8:
657	movups	$inout0,($out)		# store 8 output blocks
658	mov	$key_,$key		# restore $key
659	movdqu	($inp),$inout0		# load 8 input blocks
660	mov	$rnds_,$rounds		# restore $rounds
661	movups	$inout1,0x10($out)
662	movdqu	0x10($inp),$inout1
663	movups	$inout2,0x20($out)
664	movdqu	0x20($inp),$inout2
665	movups	$inout3,0x30($out)
666	movdqu	0x30($inp),$inout3
667	movups	$inout4,0x40($out)
668	movdqu	0x40($inp),$inout4
669	movups	$inout5,0x50($out)
670	movdqu	0x50($inp),$inout5
671	movups	$inout6,0x60($out)
672	movdqu	0x60($inp),$inout6
673	movups	$inout7,0x70($out)
674	lea	0x80($out),$out		# $out+=8*16
675	movdqu	0x70($inp),$inout7
676	lea	0x80($inp),$inp		# $inp+=8*16
677.Lecb_enc_loop8_enter:
678
679	call	_aesni_encrypt8
680
681	sub	\$0x80,$len
682	jnc	.Lecb_enc_loop8		# loop if $len-=8*16 didn't borrow
683
684	movups	$inout0,($out)		# store 8 output blocks
685	mov	$key_,$key		# restore $key
686	movups	$inout1,0x10($out)
687	mov	$rnds_,$rounds		# restore $rounds
688	movups	$inout2,0x20($out)
689	movups	$inout3,0x30($out)
690	movups	$inout4,0x40($out)
691	movups	$inout5,0x50($out)
692	movups	$inout6,0x60($out)
693	movups	$inout7,0x70($out)
694	lea	0x80($out),$out		# $out+=8*16
695	add	\$0x80,$len		# restore real remaining $len
696	jz	.Lecb_ret		# done if ($len==0)
697
698.Lecb_enc_tail:				# $len is less than 8*16
699	movups	($inp),$inout0
700	cmp	\$0x20,$len
701	jb	.Lecb_enc_one
702	movups	0x10($inp),$inout1
703	je	.Lecb_enc_two
704	movups	0x20($inp),$inout2
705	cmp	\$0x40,$len
706	jb	.Lecb_enc_three
707	movups	0x30($inp),$inout3
708	je	.Lecb_enc_four
709	movups	0x40($inp),$inout4
710	cmp	\$0x60,$len
711	jb	.Lecb_enc_five
712	movups	0x50($inp),$inout5
713	je	.Lecb_enc_six
714	movdqu	0x60($inp),$inout6
715	xorps	$inout7,$inout7
716	call	_aesni_encrypt8
717	movups	$inout0,($out)		# store 7 output blocks
718	movups	$inout1,0x10($out)
719	movups	$inout2,0x20($out)
720	movups	$inout3,0x30($out)
721	movups	$inout4,0x40($out)
722	movups	$inout5,0x50($out)
723	movups	$inout6,0x60($out)
724	jmp	.Lecb_ret
725.align	16
726.Lecb_enc_one:
727___
728	&aesni_generate1("enc",$key,$rounds);
729$code.=<<___;
730	movups	$inout0,($out)		# store one output block
731	jmp	.Lecb_ret
732.align	16
733.Lecb_enc_two:
734	call	_aesni_encrypt2
735	movups	$inout0,($out)		# store 2 output blocks
736	movups	$inout1,0x10($out)
737	jmp	.Lecb_ret
738.align	16
739.Lecb_enc_three:
740	call	_aesni_encrypt3
741	movups	$inout0,($out)		# store 3 output blocks
742	movups	$inout1,0x10($out)
743	movups	$inout2,0x20($out)
744	jmp	.Lecb_ret
745.align	16
746.Lecb_enc_four:
747	call	_aesni_encrypt4
748	movups	$inout0,($out)		# store 4 output blocks
749	movups	$inout1,0x10($out)
750	movups	$inout2,0x20($out)
751	movups	$inout3,0x30($out)
752	jmp	.Lecb_ret
753.align	16
754.Lecb_enc_five:
755	xorps	$inout5,$inout5
756	call	_aesni_encrypt6
757	movups	$inout0,($out)		# store 5 output blocks
758	movups	$inout1,0x10($out)
759	movups	$inout2,0x20($out)
760	movups	$inout3,0x30($out)
761	movups	$inout4,0x40($out)
762	jmp	.Lecb_ret
763.align	16
764.Lecb_enc_six:
765	call	_aesni_encrypt6
766	movups	$inout0,($out)		# store 6 output blocks
767	movups	$inout1,0x10($out)
768	movups	$inout2,0x20($out)
769	movups	$inout3,0x30($out)
770	movups	$inout4,0x40($out)
771	movups	$inout5,0x50($out)
772	jmp	.Lecb_ret
773#--------------------------- ECB DECRYPT ------------------------------#
774.align	16
775.Lecb_decrypt:
776	cmp	\$0x80,$len		# if ($len<8*16)
777	jb	.Lecb_dec_tail		# short input
778
779	movdqu	($inp),$inout0		# load 8 input blocks
780	movdqu	0x10($inp),$inout1
781	movdqu	0x20($inp),$inout2
782	movdqu	0x30($inp),$inout3
783	movdqu	0x40($inp),$inout4
784	movdqu	0x50($inp),$inout5
785	movdqu	0x60($inp),$inout6
786	movdqu	0x70($inp),$inout7
787	lea	0x80($inp),$inp		# $inp+=8*16
788	sub	\$0x80,$len		# $len-=8*16 (can be zero)
789	jmp	.Lecb_dec_loop8_enter
790.align 16
791.Lecb_dec_loop8:
792	movups	$inout0,($out)		# store 8 output blocks
793	mov	$key_,$key		# restore $key
794	movdqu	($inp),$inout0		# load 8 input blocks
795	mov	$rnds_,$rounds		# restore $rounds
796	movups	$inout1,0x10($out)
797	movdqu	0x10($inp),$inout1
798	movups	$inout2,0x20($out)
799	movdqu	0x20($inp),$inout2
800	movups	$inout3,0x30($out)
801	movdqu	0x30($inp),$inout3
802	movups	$inout4,0x40($out)
803	movdqu	0x40($inp),$inout4
804	movups	$inout5,0x50($out)
805	movdqu	0x50($inp),$inout5
806	movups	$inout6,0x60($out)
807	movdqu	0x60($inp),$inout6
808	movups	$inout7,0x70($out)
809	lea	0x80($out),$out		# $out+=8*16
810	movdqu	0x70($inp),$inout7
811	lea	0x80($inp),$inp		# $inp+=8*16
812.Lecb_dec_loop8_enter:
813
814	call	_aesni_decrypt8
815
816	$movkey	($key_),$rndkey0
817	sub	\$0x80,$len
818	jnc	.Lecb_dec_loop8		# loop if $len-=8*16 didn't borrow
819
820	movups	$inout0,($out)		# store 8 output blocks
821	 pxor	$inout0,$inout0		# clear register bank
822	mov	$key_,$key		# restore $key
823	movups	$inout1,0x10($out)
824	 pxor	$inout1,$inout1
825	mov	$rnds_,$rounds		# restore $rounds
826	movups	$inout2,0x20($out)
827	 pxor	$inout2,$inout2
828	movups	$inout3,0x30($out)
829	 pxor	$inout3,$inout3
830	movups	$inout4,0x40($out)
831	 pxor	$inout4,$inout4
832	movups	$inout5,0x50($out)
833	 pxor	$inout5,$inout5
834	movups	$inout6,0x60($out)
835	 pxor	$inout6,$inout6
836	movups	$inout7,0x70($out)
837	 pxor	$inout7,$inout7
838	lea	0x80($out),$out		# $out+=8*16
839	add	\$0x80,$len		# restore real remaining $len
840	jz	.Lecb_ret		# done if ($len==0)
841
842.Lecb_dec_tail:
843	movups	($inp),$inout0
844	cmp	\$0x20,$len
845	jb	.Lecb_dec_one
846	movups	0x10($inp),$inout1
847	je	.Lecb_dec_two
848	movups	0x20($inp),$inout2
849	cmp	\$0x40,$len
850	jb	.Lecb_dec_three
851	movups	0x30($inp),$inout3
852	je	.Lecb_dec_four
853	movups	0x40($inp),$inout4
854	cmp	\$0x60,$len
855	jb	.Lecb_dec_five
856	movups	0x50($inp),$inout5
857	je	.Lecb_dec_six
858	movups	0x60($inp),$inout6
859	$movkey	($key),$rndkey0
860	xorps	$inout7,$inout7
861	call	_aesni_decrypt8
862	movups	$inout0,($out)		# store 7 output blocks
863	 pxor	$inout0,$inout0		# clear register bank
864	movups	$inout1,0x10($out)
865	 pxor	$inout1,$inout1
866	movups	$inout2,0x20($out)
867	 pxor	$inout2,$inout2
868	movups	$inout3,0x30($out)
869	 pxor	$inout3,$inout3
870	movups	$inout4,0x40($out)
871	 pxor	$inout4,$inout4
872	movups	$inout5,0x50($out)
873	 pxor	$inout5,$inout5
874	movups	$inout6,0x60($out)
875	 pxor	$inout6,$inout6
876	 pxor	$inout7,$inout7
877	jmp	.Lecb_ret
878.align	16
879.Lecb_dec_one:
880___
881	&aesni_generate1("dec",$key,$rounds);
882$code.=<<___;
883	movups	$inout0,($out)		# store one output block
884	 pxor	$inout0,$inout0		# clear register bank
885	jmp	.Lecb_ret
886.align	16
887.Lecb_dec_two:
888	call	_aesni_decrypt2
889	movups	$inout0,($out)		# store 2 output blocks
890	 pxor	$inout0,$inout0		# clear register bank
891	movups	$inout1,0x10($out)
892	 pxor	$inout1,$inout1
893	jmp	.Lecb_ret
894.align	16
895.Lecb_dec_three:
896	call	_aesni_decrypt3
897	movups	$inout0,($out)		# store 3 output blocks
898	 pxor	$inout0,$inout0		# clear register bank
899	movups	$inout1,0x10($out)
900	 pxor	$inout1,$inout1
901	movups	$inout2,0x20($out)
902	 pxor	$inout2,$inout2
903	jmp	.Lecb_ret
904.align	16
905.Lecb_dec_four:
906	call	_aesni_decrypt4
907	movups	$inout0,($out)		# store 4 output blocks
908	 pxor	$inout0,$inout0		# clear register bank
909	movups	$inout1,0x10($out)
910	 pxor	$inout1,$inout1
911	movups	$inout2,0x20($out)
912	 pxor	$inout2,$inout2
913	movups	$inout3,0x30($out)
914	 pxor	$inout3,$inout3
915	jmp	.Lecb_ret
916.align	16
917.Lecb_dec_five:
918	xorps	$inout5,$inout5
919	call	_aesni_decrypt6
920	movups	$inout0,($out)		# store 5 output blocks
921	 pxor	$inout0,$inout0		# clear register bank
922	movups	$inout1,0x10($out)
923	 pxor	$inout1,$inout1
924	movups	$inout2,0x20($out)
925	 pxor	$inout2,$inout2
926	movups	$inout3,0x30($out)
927	 pxor	$inout3,$inout3
928	movups	$inout4,0x40($out)
929	 pxor	$inout4,$inout4
930	 pxor	$inout5,$inout5
931	jmp	.Lecb_ret
932.align	16
933.Lecb_dec_six:
934	call	_aesni_decrypt6
935	movups	$inout0,($out)		# store 6 output blocks
936	 pxor	$inout0,$inout0		# clear register bank
937	movups	$inout1,0x10($out)
938	 pxor	$inout1,$inout1
939	movups	$inout2,0x20($out)
940	 pxor	$inout2,$inout2
941	movups	$inout3,0x30($out)
942	 pxor	$inout3,$inout3
943	movups	$inout4,0x40($out)
944	 pxor	$inout4,$inout4
945	movups	$inout5,0x50($out)
946	 pxor	$inout5,$inout5
947
948.Lecb_ret:
949	xorps	$rndkey0,$rndkey0	# %xmm0
950	pxor	$rndkey1,$rndkey1
951___
952$code.=<<___ if ($win64);
953	movaps	(%rsp),%xmm6
954	movaps	%xmm0,(%rsp)		# clear stack
955	movaps	0x10(%rsp),%xmm7
956	movaps	%xmm0,0x10(%rsp)
957	movaps	0x20(%rsp),%xmm8
958	movaps	%xmm0,0x20(%rsp)
959	movaps	0x30(%rsp),%xmm9
960	movaps	%xmm0,0x30(%rsp)
961	lea	0x58(%rsp),%rsp
962.Lecb_enc_ret:
963___
964$code.=<<___;
965	ret
966.cfi_endproc
967.size	aesni_ecb_encrypt,.-aesni_ecb_encrypt
968___
969
970{
971######################################################################
972# void aesni_ccm64_[en|de]crypt_blocks (const void *in, void *out,
973#                         size_t blocks, const AES_KEY *key,
974#                         const char *ivec,char *cmac);
975#
976# Handles only complete blocks, operates on 64-bit counter and
977# does not update *ivec! Nor does it finalize CMAC value
978# (see engine/eng_aesni.c for details)
979#
980{
981my $cmac="%r9";	# 6th argument
982
983my $increment="%xmm9";
984my $iv="%xmm6";
985my $bswap_mask="%xmm7";
986
987$code.=<<___;
988.globl	aesni_ccm64_encrypt_blocks
989.type	aesni_ccm64_encrypt_blocks,\@function,6
990.align	16
991aesni_ccm64_encrypt_blocks:
992.cfi_startproc
993	endbranch
994___
995$code.=<<___ if ($win64);
996	lea	-0x58(%rsp),%rsp
997	movaps	%xmm6,(%rsp)		# $iv
998	movaps	%xmm7,0x10(%rsp)	# $bswap_mask
999	movaps	%xmm8,0x20(%rsp)	# $in0
1000	movaps	%xmm9,0x30(%rsp)	# $increment
1001.Lccm64_enc_body:
1002___
1003$code.=<<___;
1004	mov	240($key),$rounds		# key->rounds
1005	movdqu	($ivp),$iv
1006	movdqa	.Lincrement64(%rip),$increment
1007	movdqa	.Lbswap_mask(%rip),$bswap_mask
1008
1009	shl	\$4,$rounds
1010	mov	\$16,$rnds_
1011	lea	0($key),$key_
1012	movdqu	($cmac),$inout1
1013	movdqa	$iv,$inout0
1014	lea	32($key,$rounds),$key		# end of key schedule
1015	pshufb	$bswap_mask,$iv
1016	sub	%rax,%r10			# twisted $rounds
1017	jmp	.Lccm64_enc_outer
1018.align	16
1019.Lccm64_enc_outer:
1020	$movkey	($key_),$rndkey0
1021	mov	%r10,%rax
1022	movups	($inp),$in0			# load inp
1023
1024	xorps	$rndkey0,$inout0		# counter
1025	$movkey	16($key_),$rndkey1
1026	xorps	$in0,$rndkey0
1027	xorps	$rndkey0,$inout1		# cmac^=inp
1028	$movkey	32($key_),$rndkey0
1029
1030.Lccm64_enc2_loop:
1031	aesenc	$rndkey1,$inout0
1032	aesenc	$rndkey1,$inout1
1033	$movkey	($key,%rax),$rndkey1
1034	add	\$32,%rax
1035	aesenc	$rndkey0,$inout0
1036	aesenc	$rndkey0,$inout1
1037	$movkey	-16($key,%rax),$rndkey0
1038	jnz	.Lccm64_enc2_loop
1039	aesenc	$rndkey1,$inout0
1040	aesenc	$rndkey1,$inout1
1041	paddq	$increment,$iv
1042	dec	$len				# $len-- ($len is in blocks)
1043	aesenclast	$rndkey0,$inout0
1044	aesenclast	$rndkey0,$inout1
1045
1046	lea	16($inp),$inp
1047	xorps	$inout0,$in0			# inp ^= E(iv)
1048	movdqa	$iv,$inout0
1049	movups	$in0,($out)			# save output
1050	pshufb	$bswap_mask,$inout0
1051	lea	16($out),$out			# $out+=16
1052	jnz	.Lccm64_enc_outer		# loop if ($len!=0)
1053
1054	 pxor	$rndkey0,$rndkey0		# clear register bank
1055	 pxor	$rndkey1,$rndkey1
1056	 pxor	$inout0,$inout0
1057	movups	$inout1,($cmac)			# store resulting mac
1058	 pxor	$inout1,$inout1
1059	 pxor	$in0,$in0
1060	 pxor	$iv,$iv
1061___
1062$code.=<<___ if ($win64);
1063	movaps	(%rsp),%xmm6
1064	movaps	%xmm0,(%rsp)			# clear stack
1065	movaps	0x10(%rsp),%xmm7
1066	movaps	%xmm0,0x10(%rsp)
1067	movaps	0x20(%rsp),%xmm8
1068	movaps	%xmm0,0x20(%rsp)
1069	movaps	0x30(%rsp),%xmm9
1070	movaps	%xmm0,0x30(%rsp)
1071	lea	0x58(%rsp),%rsp
1072.Lccm64_enc_ret:
1073___
1074$code.=<<___;
1075	ret
1076.cfi_endproc
1077.size	aesni_ccm64_encrypt_blocks,.-aesni_ccm64_encrypt_blocks
1078___
1079######################################################################
1080$code.=<<___;
1081.globl	aesni_ccm64_decrypt_blocks
1082.type	aesni_ccm64_decrypt_blocks,\@function,6
1083.align	16
1084aesni_ccm64_decrypt_blocks:
1085.cfi_startproc
1086	endbranch
1087___
1088$code.=<<___ if ($win64);
1089	lea	-0x58(%rsp),%rsp
1090	movaps	%xmm6,(%rsp)		# $iv
1091	movaps	%xmm7,0x10(%rsp)	# $bswap_mask
1092	movaps	%xmm8,0x20(%rsp)	# $in8
1093	movaps	%xmm9,0x30(%rsp)	# $increment
1094.Lccm64_dec_body:
1095___
1096$code.=<<___;
1097	mov	240($key),$rounds		# key->rounds
1098	movups	($ivp),$iv
1099	movdqu	($cmac),$inout1
1100	movdqa	.Lincrement64(%rip),$increment
1101	movdqa	.Lbswap_mask(%rip),$bswap_mask
1102
1103	movaps	$iv,$inout0
1104	mov	$rounds,$rnds_
1105	mov	$key,$key_
1106	pshufb	$bswap_mask,$iv
1107___
1108	&aesni_generate1("enc",$key,$rounds);
1109$code.=<<___;
1110	shl	\$4,$rnds_
1111	mov	\$16,$rounds
1112	movups	($inp),$in0			# load inp
1113	paddq	$increment,$iv
1114	lea	16($inp),$inp			# $inp+=16
1115	sub	%r10,%rax			# twisted $rounds
1116	lea	32($key_,$rnds_),$key		# end of key schedule
1117	mov	%rax,%r10
1118	jmp	.Lccm64_dec_outer
1119.align	16
1120.Lccm64_dec_outer:
1121	xorps	$inout0,$in0			# inp ^= E(iv)
1122	movdqa	$iv,$inout0
1123	movups	$in0,($out)			# save output
1124	lea	16($out),$out			# $out+=16
1125	pshufb	$bswap_mask,$inout0
1126
1127	sub	\$1,$len			# $len-- ($len is in blocks)
1128	jz	.Lccm64_dec_break		# if ($len==0) break
1129
1130	$movkey	($key_),$rndkey0
1131	mov	%r10,%rax
1132	$movkey	16($key_),$rndkey1
1133	xorps	$rndkey0,$in0
1134	xorps	$rndkey0,$inout0
1135	xorps	$in0,$inout1			# cmac^=out
1136	$movkey	32($key_),$rndkey0
1137	jmp	.Lccm64_dec2_loop
1138.align	16
1139.Lccm64_dec2_loop:
1140	aesenc	$rndkey1,$inout0
1141	aesenc	$rndkey1,$inout1
1142	$movkey	($key,%rax),$rndkey1
1143	add	\$32,%rax
1144	aesenc	$rndkey0,$inout0
1145	aesenc	$rndkey0,$inout1
1146	$movkey	-16($key,%rax),$rndkey0
1147	jnz	.Lccm64_dec2_loop
1148	movups	($inp),$in0			# load input
1149	paddq	$increment,$iv
1150	aesenc	$rndkey1,$inout0
1151	aesenc	$rndkey1,$inout1
1152	aesenclast	$rndkey0,$inout0
1153	aesenclast	$rndkey0,$inout1
1154	lea	16($inp),$inp			# $inp+=16
1155	jmp	.Lccm64_dec_outer
1156
1157.align	16
1158.Lccm64_dec_break:
1159	#xorps	$in0,$inout1			# cmac^=out
1160	mov	240($key_),$rounds
1161___
1162	&aesni_generate1("enc",$key_,$rounds,$inout1,$in0);
1163$code.=<<___;
1164	 pxor	$rndkey0,$rndkey0		# clear register bank
1165	 pxor	$rndkey1,$rndkey1
1166	 pxor	$inout0,$inout0
1167	movups	$inout1,($cmac)			# store resulting mac
1168	 pxor	$inout1,$inout1
1169	 pxor	$in0,$in0
1170	 pxor	$iv,$iv
1171___
1172$code.=<<___ if ($win64);
1173	movaps	(%rsp),%xmm6
1174	movaps	%xmm0,(%rsp)			# clear stack
1175	movaps	0x10(%rsp),%xmm7
1176	movaps	%xmm0,0x10(%rsp)
1177	movaps	0x20(%rsp),%xmm8
1178	movaps	%xmm0,0x20(%rsp)
1179	movaps	0x30(%rsp),%xmm9
1180	movaps	%xmm0,0x30(%rsp)
1181	lea	0x58(%rsp),%rsp
1182.Lccm64_dec_ret:
1183___
1184$code.=<<___;
1185	ret
1186.cfi_endproc
1187.size	aesni_ccm64_decrypt_blocks,.-aesni_ccm64_decrypt_blocks
1188___
1189}
1190######################################################################
1191# void aesni_ctr32_encrypt_blocks (const void *in, void *out,
1192#                         size_t blocks, const AES_KEY *key,
1193#                         const char *ivec);
1194#
1195# Handles only complete blocks, operates on 32-bit counter and
1196# does not update *ivec! (see crypto/modes/ctr128.c for details)
1197#
1198# Overhaul based on suggestions from Shay Gueron and Vlad Krasnov,
1199# http://rt.openssl.org/Ticket/Display.html?id=3021&user=guest&pass=guest.
1200# Keywords are full unroll and modulo-schedule counter calculations
1201# with zero-round key xor.
1202{
1203my ($in0,$in1,$in2,$in3,$in4,$in5)=map("%xmm$_",(10..15));
1204my ($key0,$ctr)=("%ebp","${ivp}d");
1205my $frame_size = 0x80 + ($win64?160:0);
1206
1207$code.=<<___;
1208.globl	aesni_ctr32_encrypt_blocks
1209.type	aesni_ctr32_encrypt_blocks,\@function,5
1210.align	16
1211aesni_ctr32_encrypt_blocks:
1212.cfi_startproc
1213	endbranch
1214	cmp	\$1,$len
1215	jne	.Lctr32_bulk
1216
1217	# handle single block without allocating stack frame,
1218	# useful when handling edges
1219	movups	($ivp),$inout0
1220	movups	($inp),$inout1
1221	mov	240($key),%edx			# key->rounds
1222___
1223	&aesni_generate1("enc",$key,"%edx");
1224$code.=<<___;
1225	 pxor	$rndkey0,$rndkey0		# clear register bank
1226	 pxor	$rndkey1,$rndkey1
1227	xorps	$inout1,$inout0
1228	 pxor	$inout1,$inout1
1229	movups	$inout0,($out)
1230	 xorps	$inout0,$inout0
1231	jmp	.Lctr32_epilogue
1232
1233.align	16
1234.Lctr32_bulk:
1235	lea	(%rsp),$key_			# use $key_ as frame pointer
1236.cfi_def_cfa_register	$key_
1237	push	%rbp
1238.cfi_push	%rbp
1239	sub	\$$frame_size,%rsp
1240	and	\$-16,%rsp	# Linux kernel stack can be incorrectly seeded
1241___
1242$code.=<<___ if ($win64);
1243	movaps	%xmm6,-0xa8($key_)		# offload everything
1244	movaps	%xmm7,-0x98($key_)
1245	movaps	%xmm8,-0x88($key_)
1246	movaps	%xmm9,-0x78($key_)
1247	movaps	%xmm10,-0x68($key_)
1248	movaps	%xmm11,-0x58($key_)
1249	movaps	%xmm12,-0x48($key_)
1250	movaps	%xmm13,-0x38($key_)
1251	movaps	%xmm14,-0x28($key_)
1252	movaps	%xmm15,-0x18($key_)
1253.Lctr32_body:
1254___
1255$code.=<<___;
1256
1257	# 8 16-byte words on top of stack are counter values
1258	# xor-ed with zero-round key
1259
1260	movdqu	($ivp),$inout0
1261	movdqu	($key),$rndkey0
1262	mov	12($ivp),$ctr			# counter LSB
1263	pxor	$rndkey0,$inout0
1264	mov	12($key),$key0			# 0-round key LSB
1265	movdqa	$inout0,0x00(%rsp)		# populate counter block
1266	bswap	$ctr
1267	movdqa	$inout0,$inout1
1268	movdqa	$inout0,$inout2
1269	movdqa	$inout0,$inout3
1270	movdqa	$inout0,0x40(%rsp)
1271	movdqa	$inout0,0x50(%rsp)
1272	movdqa	$inout0,0x60(%rsp)
1273	mov	%rdx,%r10			# about to borrow %rdx
1274	movdqa	$inout0,0x70(%rsp)
1275
1276	lea	1($ctr),%rax
1277	 lea	2($ctr),%rdx
1278	bswap	%eax
1279	 bswap	%edx
1280	xor	$key0,%eax
1281	 xor	$key0,%edx
1282	pinsrd	\$3,%eax,$inout1
1283	lea	3($ctr),%rax
1284	movdqa	$inout1,0x10(%rsp)
1285	 pinsrd	\$3,%edx,$inout2
1286	bswap	%eax
1287	 mov	%r10,%rdx			# restore %rdx
1288	 lea	4($ctr),%r10
1289	 movdqa	$inout2,0x20(%rsp)
1290	xor	$key0,%eax
1291	 bswap	%r10d
1292	pinsrd	\$3,%eax,$inout3
1293	 xor	$key0,%r10d
1294	movdqa	$inout3,0x30(%rsp)
1295	lea	5($ctr),%r9
1296	 mov	%r10d,0x40+12(%rsp)
1297	bswap	%r9d
1298	 lea	6($ctr),%r10
1299	mov	240($key),$rounds		# key->rounds
1300	xor	$key0,%r9d
1301	 bswap	%r10d
1302	mov	%r9d,0x50+12(%rsp)
1303	 xor	$key0,%r10d
1304	lea	7($ctr),%r9
1305	 mov	%r10d,0x60+12(%rsp)
1306	bswap	%r9d
1307	 mov	OPENSSL_ia32cap_P+4(%rip),%r10d
1308	xor	$key0,%r9d
1309	 and	\$`1<<26|1<<22`,%r10d		# isolate XSAVE+MOVBE
1310	mov	%r9d,0x70+12(%rsp)
1311
1312	$movkey	0x10($key),$rndkey1
1313
1314	movdqa	0x40(%rsp),$inout4
1315	movdqa	0x50(%rsp),$inout5
1316
1317	cmp	\$8,$len		# $len is in blocks
1318	jb	.Lctr32_tail		# short input if ($len<8)
1319
1320	sub	\$6,$len		# $len is biased by -6
1321	cmp	\$`1<<22`,%r10d		# check for MOVBE without XSAVE
1322	je	.Lctr32_6x		# [which denotes Atom Silvermont]
1323
1324	lea	0x80($key),$key		# size optimization
1325	sub	\$2,$len		# $len is biased by -8
1326	jmp	.Lctr32_loop8
1327
1328.align	16
1329.Lctr32_6x:
1330	shl	\$4,$rounds
1331	mov	\$48,$rnds_
1332	bswap	$key0
1333	lea	32($key,$rounds),$key	# end of key schedule
1334	sub	%rax,%r10		# twisted $rounds
1335	jmp	.Lctr32_loop6
1336
1337.align	16
1338.Lctr32_loop6:
1339	 add	\$6,$ctr		# next counter value
1340	$movkey	-48($key,$rnds_),$rndkey0
1341	aesenc	$rndkey1,$inout0
1342	 mov	$ctr,%eax
1343	 xor	$key0,%eax
1344	aesenc	$rndkey1,$inout1
1345	 movbe	%eax,`0x00+12`(%rsp)	# store next counter value
1346	 lea	1($ctr),%eax
1347	aesenc	$rndkey1,$inout2
1348	 xor	$key0,%eax
1349	 movbe	%eax,`0x10+12`(%rsp)
1350	aesenc	$rndkey1,$inout3
1351	 lea	2($ctr),%eax
1352	 xor	$key0,%eax
1353	aesenc	$rndkey1,$inout4
1354	 movbe	%eax,`0x20+12`(%rsp)
1355	 lea	3($ctr),%eax
1356	aesenc	$rndkey1,$inout5
1357	$movkey	-32($key,$rnds_),$rndkey1
1358	 xor	$key0,%eax
1359
1360	aesenc	$rndkey0,$inout0
1361	 movbe	%eax,`0x30+12`(%rsp)
1362	 lea	4($ctr),%eax
1363	aesenc	$rndkey0,$inout1
1364	 xor	$key0,%eax
1365	 movbe	%eax,`0x40+12`(%rsp)
1366	aesenc	$rndkey0,$inout2
1367	 lea	5($ctr),%eax
1368	 xor	$key0,%eax
1369	aesenc	$rndkey0,$inout3
1370	 movbe	%eax,`0x50+12`(%rsp)
1371	 mov	%r10,%rax		# mov	$rnds_,$rounds
1372	aesenc	$rndkey0,$inout4
1373	aesenc	$rndkey0,$inout5
1374	$movkey	-16($key,$rnds_),$rndkey0
1375
1376	call	.Lenc_loop6
1377
1378	movdqu	($inp),$inout6		# load 6 input blocks
1379	movdqu	0x10($inp),$inout7
1380	movdqu	0x20($inp),$in0
1381	movdqu	0x30($inp),$in1
1382	movdqu	0x40($inp),$in2
1383	movdqu	0x50($inp),$in3
1384	lea	0x60($inp),$inp		# $inp+=6*16
1385	$movkey	-64($key,$rnds_),$rndkey1
1386	pxor	$inout0,$inout6		# inp^=E(ctr)
1387	movaps	0x00(%rsp),$inout0	# load next counter [xor-ed with 0 round]
1388	pxor	$inout1,$inout7
1389	movaps	0x10(%rsp),$inout1
1390	pxor	$inout2,$in0
1391	movaps	0x20(%rsp),$inout2
1392	pxor	$inout3,$in1
1393	movaps	0x30(%rsp),$inout3
1394	pxor	$inout4,$in2
1395	movaps	0x40(%rsp),$inout4
1396	pxor	$inout5,$in3
1397	movaps	0x50(%rsp),$inout5
1398	movdqu	$inout6,($out)		# store 6 output blocks
1399	movdqu	$inout7,0x10($out)
1400	movdqu	$in0,0x20($out)
1401	movdqu	$in1,0x30($out)
1402	movdqu	$in2,0x40($out)
1403	movdqu	$in3,0x50($out)
1404	lea	0x60($out),$out		# $out+=6*16
1405
1406	sub	\$6,$len
1407	jnc	.Lctr32_loop6		# loop if $len-=6 didn't borrow
1408
1409	add	\$6,$len		# restore real remaining $len
1410	jz	.Lctr32_done		# done if ($len==0)
1411
1412	lea	-48($rnds_),$rounds
1413	lea	-80($key,$rnds_),$key	# restore $key
1414	neg	$rounds
1415	shr	\$4,$rounds		# restore $rounds
1416	jmp	.Lctr32_tail
1417
1418.align	32
1419.Lctr32_loop8:
1420	 add		\$8,$ctr		# next counter value
1421	movdqa		0x60(%rsp),$inout6
1422	aesenc		$rndkey1,$inout0
1423	 mov		$ctr,%r9d
1424	movdqa		0x70(%rsp),$inout7
1425	aesenc		$rndkey1,$inout1
1426	 bswap		%r9d
1427	$movkey		0x20-0x80($key),$rndkey0
1428	aesenc		$rndkey1,$inout2
1429	 xor		$key0,%r9d
1430	 nop
1431	aesenc		$rndkey1,$inout3
1432	 mov		%r9d,0x00+12(%rsp)	# store next counter value
1433	 lea		1($ctr),%r9
1434	aesenc		$rndkey1,$inout4
1435	aesenc		$rndkey1,$inout5
1436	aesenc		$rndkey1,$inout6
1437	aesenc		$rndkey1,$inout7
1438	$movkey		0x30-0x80($key),$rndkey1
1439___
1440for($i=2;$i<8;$i++) {
1441my $rndkeyx = ($i&1)?$rndkey1:$rndkey0;
1442$code.=<<___;
1443	 bswap		%r9d
1444	aesenc		$rndkeyx,$inout0
1445	aesenc		$rndkeyx,$inout1
1446	 xor		$key0,%r9d
1447	 .byte		0x66,0x90
1448	aesenc		$rndkeyx,$inout2
1449	aesenc		$rndkeyx,$inout3
1450	 mov		%r9d,`0x10*($i-1)`+12(%rsp)
1451	 lea		$i($ctr),%r9
1452	aesenc		$rndkeyx,$inout4
1453	aesenc		$rndkeyx,$inout5
1454	aesenc		$rndkeyx,$inout6
1455	aesenc		$rndkeyx,$inout7
1456	$movkey		`0x20+0x10*$i`-0x80($key),$rndkeyx
1457___
1458}
1459$code.=<<___;
1460	 bswap		%r9d
1461	aesenc		$rndkey0,$inout0
1462	aesenc		$rndkey0,$inout1
1463	aesenc		$rndkey0,$inout2
1464	 xor		$key0,%r9d
1465	 movdqu		0x00($inp),$in0		# start loading input
1466	aesenc		$rndkey0,$inout3
1467	 mov		%r9d,0x70+12(%rsp)
1468	 cmp		\$11,$rounds
1469	aesenc		$rndkey0,$inout4
1470	aesenc		$rndkey0,$inout5
1471	aesenc		$rndkey0,$inout6
1472	aesenc		$rndkey0,$inout7
1473	$movkey		0xa0-0x80($key),$rndkey0
1474
1475	jb		.Lctr32_enc_done
1476
1477	aesenc		$rndkey1,$inout0
1478	aesenc		$rndkey1,$inout1
1479	aesenc		$rndkey1,$inout2
1480	aesenc		$rndkey1,$inout3
1481	aesenc		$rndkey1,$inout4
1482	aesenc		$rndkey1,$inout5
1483	aesenc		$rndkey1,$inout6
1484	aesenc		$rndkey1,$inout7
1485	$movkey		0xb0-0x80($key),$rndkey1
1486
1487	aesenc		$rndkey0,$inout0
1488	aesenc		$rndkey0,$inout1
1489	aesenc		$rndkey0,$inout2
1490	aesenc		$rndkey0,$inout3
1491	aesenc		$rndkey0,$inout4
1492	aesenc		$rndkey0,$inout5
1493	aesenc		$rndkey0,$inout6
1494	aesenc		$rndkey0,$inout7
1495	$movkey		0xc0-0x80($key),$rndkey0
1496	je		.Lctr32_enc_done
1497
1498	aesenc		$rndkey1,$inout0
1499	aesenc		$rndkey1,$inout1
1500	aesenc		$rndkey1,$inout2
1501	aesenc		$rndkey1,$inout3
1502	aesenc		$rndkey1,$inout4
1503	aesenc		$rndkey1,$inout5
1504	aesenc		$rndkey1,$inout6
1505	aesenc		$rndkey1,$inout7
1506	$movkey		0xd0-0x80($key),$rndkey1
1507
1508	aesenc		$rndkey0,$inout0
1509	aesenc		$rndkey0,$inout1
1510	aesenc		$rndkey0,$inout2
1511	aesenc		$rndkey0,$inout3
1512	aesenc		$rndkey0,$inout4
1513	aesenc		$rndkey0,$inout5
1514	aesenc		$rndkey0,$inout6
1515	aesenc		$rndkey0,$inout7
1516	$movkey		0xe0-0x80($key),$rndkey0
1517	jmp		.Lctr32_enc_done
1518
1519.align	16
1520.Lctr32_enc_done:
1521	movdqu		0x10($inp),$in1
1522	pxor		$rndkey0,$in0		# input^=round[last]
1523	movdqu		0x20($inp),$in2
1524	pxor		$rndkey0,$in1
1525	movdqu		0x30($inp),$in3
1526	pxor		$rndkey0,$in2
1527	movdqu		0x40($inp),$in4
1528	pxor		$rndkey0,$in3
1529	movdqu		0x50($inp),$in5
1530	pxor		$rndkey0,$in4
1531	pxor		$rndkey0,$in5
1532	aesenc		$rndkey1,$inout0
1533	aesenc		$rndkey1,$inout1
1534	aesenc		$rndkey1,$inout2
1535	aesenc		$rndkey1,$inout3
1536	aesenc		$rndkey1,$inout4
1537	aesenc		$rndkey1,$inout5
1538	aesenc		$rndkey1,$inout6
1539	aesenc		$rndkey1,$inout7
1540	movdqu		0x60($inp),$rndkey1	# borrow $rndkey1 for inp[6]
1541	lea		0x80($inp),$inp		# $inp+=8*16
1542
1543	aesenclast	$in0,$inout0		# $inN is inp[N]^round[last]
1544	pxor		$rndkey0,$rndkey1	# borrowed $rndkey
1545	movdqu		0x70-0x80($inp),$in0
1546	aesenclast	$in1,$inout1
1547	pxor		$rndkey0,$in0
1548	movdqa		0x00(%rsp),$in1		# load next counter block
1549	aesenclast	$in2,$inout2
1550	aesenclast	$in3,$inout3
1551	movdqa		0x10(%rsp),$in2
1552	movdqa		0x20(%rsp),$in3
1553	aesenclast	$in4,$inout4
1554	aesenclast	$in5,$inout5
1555	movdqa		0x30(%rsp),$in4
1556	movdqa		0x40(%rsp),$in5
1557	aesenclast	$rndkey1,$inout6
1558	movdqa		0x50(%rsp),$rndkey0
1559	$movkey		0x10-0x80($key),$rndkey1#real 1st-round key
1560	aesenclast	$in0,$inout7
1561
1562	movups		$inout0,($out)		# store 8 output blocks
1563	movdqa		$in1,$inout0
1564	movups		$inout1,0x10($out)
1565	movdqa		$in2,$inout1
1566	movups		$inout2,0x20($out)
1567	movdqa		$in3,$inout2
1568	movups		$inout3,0x30($out)
1569	movdqa		$in4,$inout3
1570	movups		$inout4,0x40($out)
1571	movdqa		$in5,$inout4
1572	movups		$inout5,0x50($out)
1573	movdqa		$rndkey0,$inout5
1574	movups		$inout6,0x60($out)
1575	movups		$inout7,0x70($out)
1576	lea		0x80($out),$out		# $out+=8*16
1577
1578	sub	\$8,$len
1579	jnc	.Lctr32_loop8			# loop if $len-=8 didn't borrow
1580
1581	add	\$8,$len			# restore real remaining $len
1582	jz	.Lctr32_done			# done if ($len==0)
1583	lea	-0x80($key),$key
1584
1585.Lctr32_tail:
1586	# note that at this point $inout0..5 are populated with
1587	# counter values xor-ed with 0-round key
1588	lea	16($key),$key
1589	cmp	\$4,$len
1590	jb	.Lctr32_loop3
1591	je	.Lctr32_loop4
1592
1593	# if ($len>4) compute 7 E(counter)
1594	shl		\$4,$rounds
1595	movdqa		0x60(%rsp),$inout6
1596	pxor		$inout7,$inout7
1597
1598	$movkey		16($key),$rndkey0
1599	aesenc		$rndkey1,$inout0
1600	aesenc		$rndkey1,$inout1
1601	lea		32-16($key,$rounds),$key# prepare for .Lenc_loop8_enter
1602	neg		%rax
1603	aesenc		$rndkey1,$inout2
1604	add		\$16,%rax		# prepare for .Lenc_loop8_enter
1605	 movups		($inp),$in0
1606	aesenc		$rndkey1,$inout3
1607	aesenc		$rndkey1,$inout4
1608	 movups		0x10($inp),$in1		# pre-load input
1609	 movups		0x20($inp),$in2
1610	aesenc		$rndkey1,$inout5
1611	aesenc		$rndkey1,$inout6
1612
1613	call            .Lenc_loop8_enter
1614
1615	movdqu	0x30($inp),$in3
1616	pxor	$in0,$inout0
1617	movdqu	0x40($inp),$in0
1618	pxor	$in1,$inout1
1619	movdqu	$inout0,($out)			# store output
1620	pxor	$in2,$inout2
1621	movdqu	$inout1,0x10($out)
1622	pxor	$in3,$inout3
1623	movdqu	$inout2,0x20($out)
1624	pxor	$in0,$inout4
1625	movdqu	$inout3,0x30($out)
1626	movdqu	$inout4,0x40($out)
1627	cmp	\$6,$len
1628	jb	.Lctr32_done			# $len was 5, stop store
1629
1630	movups	0x50($inp),$in1
1631	xorps	$in1,$inout5
1632	movups	$inout5,0x50($out)
1633	je	.Lctr32_done			# $len was 6, stop store
1634
1635	movups	0x60($inp),$in2
1636	xorps	$in2,$inout6
1637	movups	$inout6,0x60($out)
1638	jmp	.Lctr32_done			# $len was 7, stop store
1639
1640.align	32
1641.Lctr32_loop4:
1642	aesenc		$rndkey1,$inout0
1643	lea		16($key),$key
1644	dec		$rounds
1645	aesenc		$rndkey1,$inout1
1646	aesenc		$rndkey1,$inout2
1647	aesenc		$rndkey1,$inout3
1648	$movkey		($key),$rndkey1
1649	jnz		.Lctr32_loop4
1650	aesenclast	$rndkey1,$inout0
1651	aesenclast	$rndkey1,$inout1
1652	 movups		($inp),$in0		# load input
1653	 movups		0x10($inp),$in1
1654	aesenclast	$rndkey1,$inout2
1655	aesenclast	$rndkey1,$inout3
1656	 movups		0x20($inp),$in2
1657	 movups		0x30($inp),$in3
1658
1659	xorps	$in0,$inout0
1660	movups	$inout0,($out)			# store output
1661	xorps	$in1,$inout1
1662	movups	$inout1,0x10($out)
1663	pxor	$in2,$inout2
1664	movdqu	$inout2,0x20($out)
1665	pxor	$in3,$inout3
1666	movdqu	$inout3,0x30($out)
1667	jmp	.Lctr32_done			# $len was 4, stop store
1668
1669.align	32
1670.Lctr32_loop3:
1671	aesenc		$rndkey1,$inout0
1672	lea		16($key),$key
1673	dec		$rounds
1674	aesenc		$rndkey1,$inout1
1675	aesenc		$rndkey1,$inout2
1676	$movkey		($key),$rndkey1
1677	jnz		.Lctr32_loop3
1678	aesenclast	$rndkey1,$inout0
1679	aesenclast	$rndkey1,$inout1
1680	aesenclast	$rndkey1,$inout2
1681
1682	movups	($inp),$in0			# load input
1683	xorps	$in0,$inout0
1684	movups	$inout0,($out)			# store output
1685	cmp	\$2,$len
1686	jb	.Lctr32_done			# $len was 1, stop store
1687
1688	movups	0x10($inp),$in1
1689	xorps	$in1,$inout1
1690	movups	$inout1,0x10($out)
1691	je	.Lctr32_done			# $len was 2, stop store
1692
1693	movups	0x20($inp),$in2
1694	xorps	$in2,$inout2
1695	movups	$inout2,0x20($out)		# $len was 3, stop store
1696
1697.Lctr32_done:
1698	xorps	%xmm0,%xmm0			# clear register bank
1699	xor	$key0,$key0
1700	pxor	%xmm1,%xmm1
1701	pxor	%xmm2,%xmm2
1702	pxor	%xmm3,%xmm3
1703	pxor	%xmm4,%xmm4
1704	pxor	%xmm5,%xmm5
1705___
1706$code.=<<___ if (!$win64);
1707	pxor	%xmm6,%xmm6
1708	pxor	%xmm7,%xmm7
1709	movaps	%xmm0,0x00(%rsp)		# clear stack
1710	pxor	%xmm8,%xmm8
1711	movaps	%xmm0,0x10(%rsp)
1712	pxor	%xmm9,%xmm9
1713	movaps	%xmm0,0x20(%rsp)
1714	pxor	%xmm10,%xmm10
1715	movaps	%xmm0,0x30(%rsp)
1716	pxor	%xmm11,%xmm11
1717	movaps	%xmm0,0x40(%rsp)
1718	pxor	%xmm12,%xmm12
1719	movaps	%xmm0,0x50(%rsp)
1720	pxor	%xmm13,%xmm13
1721	movaps	%xmm0,0x60(%rsp)
1722	pxor	%xmm14,%xmm14
1723	movaps	%xmm0,0x70(%rsp)
1724	pxor	%xmm15,%xmm15
1725___
1726$code.=<<___ if ($win64);
1727	movaps	-0xa8($key_),%xmm6
1728	movaps	%xmm0,-0xa8($key_)		# clear stack
1729	movaps	-0x98($key_),%xmm7
1730	movaps	%xmm0,-0x98($key_)
1731	movaps	-0x88($key_),%xmm8
1732	movaps	%xmm0,-0x88($key_)
1733	movaps	-0x78($key_),%xmm9
1734	movaps	%xmm0,-0x78($key_)
1735	movaps	-0x68($key_),%xmm10
1736	movaps	%xmm0,-0x68($key_)
1737	movaps	-0x58($key_),%xmm11
1738	movaps	%xmm0,-0x58($key_)
1739	movaps	-0x48($key_),%xmm12
1740	movaps	%xmm0,-0x48($key_)
1741	movaps	-0x38($key_),%xmm13
1742	movaps	%xmm0,-0x38($key_)
1743	movaps	-0x28($key_),%xmm14
1744	movaps	%xmm0,-0x28($key_)
1745	movaps	-0x18($key_),%xmm15
1746	movaps	%xmm0,-0x18($key_)
1747	movaps	%xmm0,0x00(%rsp)
1748	movaps	%xmm0,0x10(%rsp)
1749	movaps	%xmm0,0x20(%rsp)
1750	movaps	%xmm0,0x30(%rsp)
1751	movaps	%xmm0,0x40(%rsp)
1752	movaps	%xmm0,0x50(%rsp)
1753	movaps	%xmm0,0x60(%rsp)
1754	movaps	%xmm0,0x70(%rsp)
1755___
1756$code.=<<___;
1757	mov	-8($key_),%rbp
1758.cfi_restore	%rbp
1759	lea	($key_),%rsp
1760.cfi_def_cfa_register	%rsp
1761.Lctr32_epilogue:
1762	ret
1763.cfi_endproc
1764.size	aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks
1765___
1766}
1767
1768######################################################################
1769# void aesni_xts_[en|de]crypt(const char *inp,char *out,size_t len,
1770#	const AES_KEY *key1, const AES_KEY *key2
1771#	const unsigned char iv[16]);
1772#
1773{
1774my @tweak=map("%xmm$_",(10..15));
1775my ($twmask,$twres,$twtmp)=("%xmm8","%xmm9",@tweak[4]);
1776my ($key2,$ivp,$len_)=("%r8","%r9","%r9");
1777my $frame_size = 0x70 + ($win64?160:0);
1778my $key_ = "%rbp";	# override so that we can use %r11 as FP
1779
1780$code.=<<___;
1781.globl	aesni_xts_encrypt
1782.type	aesni_xts_encrypt,\@function,6
1783.align	16
1784aesni_xts_encrypt:
1785.cfi_startproc
1786	endbranch
1787	lea	(%rsp),%r11			# frame pointer
1788.cfi_def_cfa_register	%r11
1789	push	%rbp
1790.cfi_push	%rbp
1791	sub	\$$frame_size,%rsp
1792	and	\$-16,%rsp	# Linux kernel stack can be incorrectly seeded
1793___
1794$code.=<<___ if ($win64);
1795	movaps	%xmm6,-0xa8(%r11)		# offload everything
1796	movaps	%xmm7,-0x98(%r11)
1797	movaps	%xmm8,-0x88(%r11)
1798	movaps	%xmm9,-0x78(%r11)
1799	movaps	%xmm10,-0x68(%r11)
1800	movaps	%xmm11,-0x58(%r11)
1801	movaps	%xmm12,-0x48(%r11)
1802	movaps	%xmm13,-0x38(%r11)
1803	movaps	%xmm14,-0x28(%r11)
1804	movaps	%xmm15,-0x18(%r11)
1805.Lxts_enc_body:
1806___
1807$code.=<<___;
1808	movups	($ivp),$inout0			# load clear-text tweak
1809	mov	240(%r8),$rounds		# key2->rounds
1810	mov	240($key),$rnds_		# key1->rounds
1811___
1812	# generate the tweak
1813	&aesni_generate1("enc",$key2,$rounds,$inout0);
1814$code.=<<___;
1815	$movkey	($key),$rndkey0			# zero round key
1816	mov	$key,$key_			# backup $key
1817	mov	$rnds_,$rounds			# backup $rounds
1818	shl	\$4,$rnds_
1819	mov	$len,$len_			# backup $len
1820	and	\$-16,$len
1821
1822	$movkey	16($key,$rnds_),$rndkey1	# last round key
1823
1824	movdqa	.Lxts_magic(%rip),$twmask
1825	movdqa	$inout0,@tweak[5]
1826	pshufd	\$0x5f,$inout0,$twres
1827	pxor	$rndkey0,$rndkey1
1828___
1829    # alternative tweak calculation algorithm is based on suggestions
1830    # by Shay Gueron. psrad doesn't conflict with AES-NI instructions
1831    # and should help in the future...
1832    for ($i=0;$i<4;$i++) {
1833    $code.=<<___;
1834	movdqa	$twres,$twtmp
1835	paddd	$twres,$twres
1836	movdqa	@tweak[5],@tweak[$i]
1837	psrad	\$31,$twtmp			# broadcast upper bits
1838	paddq	@tweak[5],@tweak[5]
1839	pand	$twmask,$twtmp
1840	pxor	$rndkey0,@tweak[$i]
1841	pxor	$twtmp,@tweak[5]
1842___
1843    }
1844$code.=<<___;
1845	movdqa	@tweak[5],@tweak[4]
1846	psrad	\$31,$twres
1847	paddq	@tweak[5],@tweak[5]
1848	pand	$twmask,$twres
1849	pxor	$rndkey0,@tweak[4]
1850	pxor	$twres,@tweak[5]
1851	movaps	$rndkey1,0x60(%rsp)		# save round[0]^round[last]
1852
1853	sub	\$16*6,$len
1854	jc	.Lxts_enc_short			# if $len-=6*16 borrowed
1855
1856	mov	\$16+96,$rounds
1857	lea	32($key_,$rnds_),$key		# end of key schedule
1858	sub	%r10,%rax			# twisted $rounds
1859	$movkey	16($key_),$rndkey1
1860	mov	%rax,%r10			# backup twisted $rounds
1861	lea	.Lxts_magic(%rip),%r8
1862	jmp	.Lxts_enc_grandloop
1863
1864.align	32
1865.Lxts_enc_grandloop:
1866	movdqu	`16*0`($inp),$inout0		# load input
1867	movdqa	$rndkey0,$twmask
1868	movdqu	`16*1`($inp),$inout1
1869	pxor	@tweak[0],$inout0		# input^=tweak^round[0]
1870	movdqu	`16*2`($inp),$inout2
1871	pxor	@tweak[1],$inout1
1872	 aesenc		$rndkey1,$inout0
1873	movdqu	`16*3`($inp),$inout3
1874	pxor	@tweak[2],$inout2
1875	 aesenc		$rndkey1,$inout1
1876	movdqu	`16*4`($inp),$inout4
1877	pxor	@tweak[3],$inout3
1878	 aesenc		$rndkey1,$inout2
1879	movdqu	`16*5`($inp),$inout5
1880	pxor	@tweak[5],$twmask		# round[0]^=tweak[5]
1881	 movdqa	0x60(%rsp),$twres		# load round[0]^round[last]
1882	pxor	@tweak[4],$inout4
1883	 aesenc		$rndkey1,$inout3
1884	$movkey	32($key_),$rndkey0
1885	lea	`16*6`($inp),$inp
1886	pxor	$twmask,$inout5
1887
1888	 pxor	$twres,@tweak[0]		# calculate tweaks^round[last]
1889	aesenc		$rndkey1,$inout4
1890	 pxor	$twres,@tweak[1]
1891	 movdqa	@tweak[0],`16*0`(%rsp)		# put aside tweaks^round[last]
1892	aesenc		$rndkey1,$inout5
1893	$movkey		48($key_),$rndkey1
1894	 pxor	$twres,@tweak[2]
1895
1896	aesenc		$rndkey0,$inout0
1897	 pxor	$twres,@tweak[3]
1898	 movdqa	@tweak[1],`16*1`(%rsp)
1899	aesenc		$rndkey0,$inout1
1900	 pxor	$twres,@tweak[4]
1901	 movdqa	@tweak[2],`16*2`(%rsp)
1902	aesenc		$rndkey0,$inout2
1903	aesenc		$rndkey0,$inout3
1904	 pxor	$twres,$twmask
1905	 movdqa	@tweak[4],`16*4`(%rsp)
1906	aesenc		$rndkey0,$inout4
1907	aesenc		$rndkey0,$inout5
1908	$movkey		64($key_),$rndkey0
1909	 movdqa	$twmask,`16*5`(%rsp)
1910	pshufd	\$0x5f,@tweak[5],$twres
1911	jmp	.Lxts_enc_loop6
1912.align	32
1913.Lxts_enc_loop6:
1914	aesenc		$rndkey1,$inout0
1915	aesenc		$rndkey1,$inout1
1916	aesenc		$rndkey1,$inout2
1917	aesenc		$rndkey1,$inout3
1918	aesenc		$rndkey1,$inout4
1919	aesenc		$rndkey1,$inout5
1920	$movkey		-64($key,%rax),$rndkey1
1921	add		\$32,%rax
1922
1923	aesenc		$rndkey0,$inout0
1924	aesenc		$rndkey0,$inout1
1925	aesenc		$rndkey0,$inout2
1926	aesenc		$rndkey0,$inout3
1927	aesenc		$rndkey0,$inout4
1928	aesenc		$rndkey0,$inout5
1929	$movkey		-80($key,%rax),$rndkey0
1930	jnz		.Lxts_enc_loop6
1931
1932	movdqa	(%r8),$twmask			# start calculating next tweak
1933	movdqa	$twres,$twtmp
1934	paddd	$twres,$twres
1935	 aesenc		$rndkey1,$inout0
1936	paddq	@tweak[5],@tweak[5]
1937	psrad	\$31,$twtmp
1938	 aesenc		$rndkey1,$inout1
1939	pand	$twmask,$twtmp
1940	$movkey	($key_),@tweak[0]		# load round[0]
1941	 aesenc		$rndkey1,$inout2
1942	 aesenc		$rndkey1,$inout3
1943	 aesenc		$rndkey1,$inout4
1944	pxor	$twtmp,@tweak[5]
1945	movaps	@tweak[0],@tweak[1]		# copy round[0]
1946	 aesenc		$rndkey1,$inout5
1947	 $movkey	-64($key),$rndkey1
1948
1949	movdqa	$twres,$twtmp
1950	 aesenc		$rndkey0,$inout0
1951	paddd	$twres,$twres
1952	pxor	@tweak[5],@tweak[0]
1953	 aesenc		$rndkey0,$inout1
1954	psrad	\$31,$twtmp
1955	paddq	@tweak[5],@tweak[5]
1956	 aesenc		$rndkey0,$inout2
1957	 aesenc		$rndkey0,$inout3
1958	pand	$twmask,$twtmp
1959	movaps	@tweak[1],@tweak[2]
1960	 aesenc		$rndkey0,$inout4
1961	pxor	$twtmp,@tweak[5]
1962	movdqa	$twres,$twtmp
1963	 aesenc		$rndkey0,$inout5
1964	 $movkey	-48($key),$rndkey0
1965
1966	paddd	$twres,$twres
1967	 aesenc		$rndkey1,$inout0
1968	pxor	@tweak[5],@tweak[1]
1969	psrad	\$31,$twtmp
1970	 aesenc		$rndkey1,$inout1
1971	paddq	@tweak[5],@tweak[5]
1972	pand	$twmask,$twtmp
1973	 aesenc		$rndkey1,$inout2
1974	 aesenc		$rndkey1,$inout3
1975	 movdqa	@tweak[3],`16*3`(%rsp)
1976	pxor	$twtmp,@tweak[5]
1977	 aesenc		$rndkey1,$inout4
1978	movaps	@tweak[2],@tweak[3]
1979	movdqa	$twres,$twtmp
1980	 aesenc		$rndkey1,$inout5
1981	 $movkey	-32($key),$rndkey1
1982
1983	paddd	$twres,$twres
1984	 aesenc		$rndkey0,$inout0
1985	pxor	@tweak[5],@tweak[2]
1986	psrad	\$31,$twtmp
1987	 aesenc		$rndkey0,$inout1
1988	paddq	@tweak[5],@tweak[5]
1989	pand	$twmask,$twtmp
1990	 aesenc		$rndkey0,$inout2
1991	 aesenc		$rndkey0,$inout3
1992	 aesenc		$rndkey0,$inout4
1993	pxor	$twtmp,@tweak[5]
1994	movaps	@tweak[3],@tweak[4]
1995	 aesenc		$rndkey0,$inout5
1996
1997	movdqa	$twres,$rndkey0
1998	paddd	$twres,$twres
1999	 aesenc		$rndkey1,$inout0
2000	pxor	@tweak[5],@tweak[3]
2001	psrad	\$31,$rndkey0
2002	 aesenc		$rndkey1,$inout1
2003	paddq	@tweak[5],@tweak[5]
2004	pand	$twmask,$rndkey0
2005	 aesenc		$rndkey1,$inout2
2006	 aesenc		$rndkey1,$inout3
2007	pxor	$rndkey0,@tweak[5]
2008	$movkey		($key_),$rndkey0
2009	 aesenc		$rndkey1,$inout4
2010	 aesenc		$rndkey1,$inout5
2011	$movkey		16($key_),$rndkey1
2012
2013	pxor	@tweak[5],@tweak[4]
2014	 aesenclast	`16*0`(%rsp),$inout0
2015	psrad	\$31,$twres
2016	paddq	@tweak[5],@tweak[5]
2017	 aesenclast	`16*1`(%rsp),$inout1
2018	 aesenclast	`16*2`(%rsp),$inout2
2019	pand	$twmask,$twres
2020	mov	%r10,%rax			# restore $rounds
2021	 aesenclast	`16*3`(%rsp),$inout3
2022	 aesenclast	`16*4`(%rsp),$inout4
2023	 aesenclast	`16*5`(%rsp),$inout5
2024	pxor	$twres,@tweak[5]
2025
2026	lea	`16*6`($out),$out		# $out+=6*16
2027	movups	$inout0,`-16*6`($out)		# store 6 output blocks
2028	movups	$inout1,`-16*5`($out)
2029	movups	$inout2,`-16*4`($out)
2030	movups	$inout3,`-16*3`($out)
2031	movups	$inout4,`-16*2`($out)
2032	movups	$inout5,`-16*1`($out)
2033	sub	\$16*6,$len
2034	jnc	.Lxts_enc_grandloop		# loop if $len-=6*16 didn't borrow
2035
2036	mov	\$16+96,$rounds
2037	sub	$rnds_,$rounds
2038	mov	$key_,$key			# restore $key
2039	shr	\$4,$rounds			# restore original value
2040
2041.Lxts_enc_short:
2042	# at the point @tweak[0..5] are populated with tweak values
2043	mov	$rounds,$rnds_			# backup $rounds
2044	pxor	$rndkey0,@tweak[0]
2045	add	\$16*6,$len			# restore real remaining $len
2046	jz	.Lxts_enc_done			# done if ($len==0)
2047
2048	pxor	$rndkey0,@tweak[1]
2049	cmp	\$0x20,$len
2050	jb	.Lxts_enc_one			# $len is 1*16
2051	pxor	$rndkey0,@tweak[2]
2052	je	.Lxts_enc_two			# $len is 2*16
2053
2054	pxor	$rndkey0,@tweak[3]
2055	cmp	\$0x40,$len
2056	jb	.Lxts_enc_three			# $len is 3*16
2057	pxor	$rndkey0,@tweak[4]
2058	je	.Lxts_enc_four			# $len is 4*16
2059
2060	movdqu	($inp),$inout0			# $len is 5*16
2061	movdqu	16*1($inp),$inout1
2062	movdqu	16*2($inp),$inout2
2063	pxor	@tweak[0],$inout0
2064	movdqu	16*3($inp),$inout3
2065	pxor	@tweak[1],$inout1
2066	movdqu	16*4($inp),$inout4
2067	lea	16*5($inp),$inp			# $inp+=5*16
2068	pxor	@tweak[2],$inout2
2069	pxor	@tweak[3],$inout3
2070	pxor	@tweak[4],$inout4
2071	pxor	$inout5,$inout5
2072
2073	call	_aesni_encrypt6
2074
2075	xorps	@tweak[0],$inout0
2076	movdqa	@tweak[5],@tweak[0]
2077	xorps	@tweak[1],$inout1
2078	xorps	@tweak[2],$inout2
2079	movdqu	$inout0,($out)			# store 5 output blocks
2080	xorps	@tweak[3],$inout3
2081	movdqu	$inout1,16*1($out)
2082	xorps	@tweak[4],$inout4
2083	movdqu	$inout2,16*2($out)
2084	movdqu	$inout3,16*3($out)
2085	movdqu	$inout4,16*4($out)
2086	lea	16*5($out),$out			# $out+=5*16
2087	jmp	.Lxts_enc_done
2088
2089.align	16
2090.Lxts_enc_one:
2091	movups	($inp),$inout0
2092	lea	16*1($inp),$inp			# inp+=1*16
2093	xorps	@tweak[0],$inout0
2094___
2095	&aesni_generate1("enc",$key,$rounds);
2096$code.=<<___;
2097	xorps	@tweak[0],$inout0
2098	movdqa	@tweak[1],@tweak[0]
2099	movups	$inout0,($out)			# store one output block
2100	lea	16*1($out),$out			# $out+=1*16
2101	jmp	.Lxts_enc_done
2102
2103.align	16
2104.Lxts_enc_two:
2105	movups	($inp),$inout0
2106	movups	16($inp),$inout1
2107	lea	32($inp),$inp			# $inp+=2*16
2108	xorps	@tweak[0],$inout0
2109	xorps	@tweak[1],$inout1
2110
2111	call	_aesni_encrypt2
2112
2113	xorps	@tweak[0],$inout0
2114	movdqa	@tweak[2],@tweak[0]
2115	xorps	@tweak[1],$inout1
2116	movups	$inout0,($out)			# store 2 output blocks
2117	movups	$inout1,16*1($out)
2118	lea	16*2($out),$out			# $out+=2*16
2119	jmp	.Lxts_enc_done
2120
2121.align	16
2122.Lxts_enc_three:
2123	movups	($inp),$inout0
2124	movups	16*1($inp),$inout1
2125	movups	16*2($inp),$inout2
2126	lea	16*3($inp),$inp			# $inp+=3*16
2127	xorps	@tweak[0],$inout0
2128	xorps	@tweak[1],$inout1
2129	xorps	@tweak[2],$inout2
2130
2131	call	_aesni_encrypt3
2132
2133	xorps	@tweak[0],$inout0
2134	movdqa	@tweak[3],@tweak[0]
2135	xorps	@tweak[1],$inout1
2136	xorps	@tweak[2],$inout2
2137	movups	$inout0,($out)			# store 3 output blocks
2138	movups	$inout1,16*1($out)
2139	movups	$inout2,16*2($out)
2140	lea	16*3($out),$out			# $out+=3*16
2141	jmp	.Lxts_enc_done
2142
2143.align	16
2144.Lxts_enc_four:
2145	movups	($inp),$inout0
2146	movups	16*1($inp),$inout1
2147	movups	16*2($inp),$inout2
2148	xorps	@tweak[0],$inout0
2149	movups	16*3($inp),$inout3
2150	lea	16*4($inp),$inp			# $inp+=4*16
2151	xorps	@tweak[1],$inout1
2152	xorps	@tweak[2],$inout2
2153	xorps	@tweak[3],$inout3
2154
2155	call	_aesni_encrypt4
2156
2157	pxor	@tweak[0],$inout0
2158	movdqa	@tweak[4],@tweak[0]
2159	pxor	@tweak[1],$inout1
2160	pxor	@tweak[2],$inout2
2161	movdqu	$inout0,($out)			# store 4 output blocks
2162	pxor	@tweak[3],$inout3
2163	movdqu	$inout1,16*1($out)
2164	movdqu	$inout2,16*2($out)
2165	movdqu	$inout3,16*3($out)
2166	lea	16*4($out),$out			# $out+=4*16
2167	jmp	.Lxts_enc_done
2168
2169.align	16
2170.Lxts_enc_done:
2171	and	\$15,$len_			# see if $len%16 is 0
2172	jz	.Lxts_enc_ret
2173	mov	$len_,$len
2174
2175.Lxts_enc_steal:
2176	movzb	($inp),%eax			# borrow $rounds ...
2177	movzb	-16($out),%ecx			# ... and $key
2178	lea	1($inp),$inp
2179	mov	%al,-16($out)
2180	mov	%cl,0($out)
2181	lea	1($out),$out
2182	sub	\$1,$len
2183	jnz	.Lxts_enc_steal
2184
2185	sub	$len_,$out			# rewind $out
2186	mov	$key_,$key			# restore $key
2187	mov	$rnds_,$rounds			# restore $rounds
2188
2189	movups	-16($out),$inout0
2190	xorps	@tweak[0],$inout0
2191___
2192	&aesni_generate1("enc",$key,$rounds);
2193$code.=<<___;
2194	xorps	@tweak[0],$inout0
2195	movups	$inout0,-16($out)
2196
2197.Lxts_enc_ret:
2198	xorps	%xmm0,%xmm0			# clear register bank
2199	pxor	%xmm1,%xmm1
2200	pxor	%xmm2,%xmm2
2201	pxor	%xmm3,%xmm3
2202	pxor	%xmm4,%xmm4
2203	pxor	%xmm5,%xmm5
2204___
2205$code.=<<___ if (!$win64);
2206	pxor	%xmm6,%xmm6
2207	pxor	%xmm7,%xmm7
2208	movaps	%xmm0,0x00(%rsp)		# clear stack
2209	pxor	%xmm8,%xmm8
2210	movaps	%xmm0,0x10(%rsp)
2211	pxor	%xmm9,%xmm9
2212	movaps	%xmm0,0x20(%rsp)
2213	pxor	%xmm10,%xmm10
2214	movaps	%xmm0,0x30(%rsp)
2215	pxor	%xmm11,%xmm11
2216	movaps	%xmm0,0x40(%rsp)
2217	pxor	%xmm12,%xmm12
2218	movaps	%xmm0,0x50(%rsp)
2219	pxor	%xmm13,%xmm13
2220	movaps	%xmm0,0x60(%rsp)
2221	pxor	%xmm14,%xmm14
2222	pxor	%xmm15,%xmm15
2223___
2224$code.=<<___ if ($win64);
2225	movaps	-0xa8(%r11),%xmm6
2226	movaps	%xmm0,-0xa8(%r11)		# clear stack
2227	movaps	-0x98(%r11),%xmm7
2228	movaps	%xmm0,-0x98(%r11)
2229	movaps	-0x88(%r11),%xmm8
2230	movaps	%xmm0,-0x88(%r11)
2231	movaps	-0x78(%r11),%xmm9
2232	movaps	%xmm0,-0x78(%r11)
2233	movaps	-0x68(%r11),%xmm10
2234	movaps	%xmm0,-0x68(%r11)
2235	movaps	-0x58(%r11),%xmm11
2236	movaps	%xmm0,-0x58(%r11)
2237	movaps	-0x48(%r11),%xmm12
2238	movaps	%xmm0,-0x48(%r11)
2239	movaps	-0x38(%r11),%xmm13
2240	movaps	%xmm0,-0x38(%r11)
2241	movaps	-0x28(%r11),%xmm14
2242	movaps	%xmm0,-0x28(%r11)
2243	movaps	-0x18(%r11),%xmm15
2244	movaps	%xmm0,-0x18(%r11)
2245	movaps	%xmm0,0x00(%rsp)
2246	movaps	%xmm0,0x10(%rsp)
2247	movaps	%xmm0,0x20(%rsp)
2248	movaps	%xmm0,0x30(%rsp)
2249	movaps	%xmm0,0x40(%rsp)
2250	movaps	%xmm0,0x50(%rsp)
2251	movaps	%xmm0,0x60(%rsp)
2252___
2253$code.=<<___;
2254	mov	-8(%r11),%rbp
2255.cfi_restore	%rbp
2256	lea	(%r11),%rsp
2257.cfi_def_cfa_register	%rsp
2258.Lxts_enc_epilogue:
2259	ret
2260.cfi_endproc
2261.size	aesni_xts_encrypt,.-aesni_xts_encrypt
2262___
2263
2264$code.=<<___;
2265.globl	aesni_xts_decrypt
2266.type	aesni_xts_decrypt,\@function,6
2267.align	16
2268aesni_xts_decrypt:
2269.cfi_startproc
2270	endbranch
2271	lea	(%rsp),%r11			# frame pointer
2272.cfi_def_cfa_register	%r11
2273	push	%rbp
2274.cfi_push	%rbp
2275	sub	\$$frame_size,%rsp
2276	and	\$-16,%rsp	# Linux kernel stack can be incorrectly seeded
2277___
2278$code.=<<___ if ($win64);
2279	movaps	%xmm6,-0xa8(%r11)		# offload everything
2280	movaps	%xmm7,-0x98(%r11)
2281	movaps	%xmm8,-0x88(%r11)
2282	movaps	%xmm9,-0x78(%r11)
2283	movaps	%xmm10,-0x68(%r11)
2284	movaps	%xmm11,-0x58(%r11)
2285	movaps	%xmm12,-0x48(%r11)
2286	movaps	%xmm13,-0x38(%r11)
2287	movaps	%xmm14,-0x28(%r11)
2288	movaps	%xmm15,-0x18(%r11)
2289.Lxts_dec_body:
2290___
2291$code.=<<___;
2292	movups	($ivp),$inout0			# load clear-text tweak
2293	mov	240($key2),$rounds		# key2->rounds
2294	mov	240($key),$rnds_		# key1->rounds
2295___
2296	# generate the tweak
2297	&aesni_generate1("enc",$key2,$rounds,$inout0);
2298$code.=<<___;
2299	xor	%eax,%eax			# if ($len%16) len-=16;
2300	test	\$15,$len
2301	setnz	%al
2302	shl	\$4,%rax
2303	sub	%rax,$len
2304
2305	$movkey	($key),$rndkey0			# zero round key
2306	mov	$key,$key_			# backup $key
2307	mov	$rnds_,$rounds			# backup $rounds
2308	shl	\$4,$rnds_
2309	mov	$len,$len_			# backup $len
2310	and	\$-16,$len
2311
2312	$movkey	16($key,$rnds_),$rndkey1	# last round key
2313
2314	movdqa	.Lxts_magic(%rip),$twmask
2315	movdqa	$inout0,@tweak[5]
2316	pshufd	\$0x5f,$inout0,$twres
2317	pxor	$rndkey0,$rndkey1
2318___
2319    for ($i=0;$i<4;$i++) {
2320    $code.=<<___;
2321	movdqa	$twres,$twtmp
2322	paddd	$twres,$twres
2323	movdqa	@tweak[5],@tweak[$i]
2324	psrad	\$31,$twtmp			# broadcast upper bits
2325	paddq	@tweak[5],@tweak[5]
2326	pand	$twmask,$twtmp
2327	pxor	$rndkey0,@tweak[$i]
2328	pxor	$twtmp,@tweak[5]
2329___
2330    }
2331$code.=<<___;
2332	movdqa	@tweak[5],@tweak[4]
2333	psrad	\$31,$twres
2334	paddq	@tweak[5],@tweak[5]
2335	pand	$twmask,$twres
2336	pxor	$rndkey0,@tweak[4]
2337	pxor	$twres,@tweak[5]
2338	movaps	$rndkey1,0x60(%rsp)		# save round[0]^round[last]
2339
2340	sub	\$16*6,$len
2341	jc	.Lxts_dec_short			# if $len-=6*16 borrowed
2342
2343	mov	\$16+96,$rounds
2344	lea	32($key_,$rnds_),$key		# end of key schedule
2345	sub	%r10,%rax			# twisted $rounds
2346	$movkey	16($key_),$rndkey1
2347	mov	%rax,%r10			# backup twisted $rounds
2348	lea	.Lxts_magic(%rip),%r8
2349	jmp	.Lxts_dec_grandloop
2350
2351.align	32
2352.Lxts_dec_grandloop:
2353	movdqu	`16*0`($inp),$inout0		# load input
2354	movdqa	$rndkey0,$twmask
2355	movdqu	`16*1`($inp),$inout1
2356	pxor	@tweak[0],$inout0		# input^=tweak^round[0]
2357	movdqu	`16*2`($inp),$inout2
2358	pxor	@tweak[1],$inout1
2359	 aesdec		$rndkey1,$inout0
2360	movdqu	`16*3`($inp),$inout3
2361	pxor	@tweak[2],$inout2
2362	 aesdec		$rndkey1,$inout1
2363	movdqu	`16*4`($inp),$inout4
2364	pxor	@tweak[3],$inout3
2365	 aesdec		$rndkey1,$inout2
2366	movdqu	`16*5`($inp),$inout5
2367	pxor	@tweak[5],$twmask		# round[0]^=tweak[5]
2368	 movdqa	0x60(%rsp),$twres		# load round[0]^round[last]
2369	pxor	@tweak[4],$inout4
2370	 aesdec		$rndkey1,$inout3
2371	$movkey	32($key_),$rndkey0
2372	lea	`16*6`($inp),$inp
2373	pxor	$twmask,$inout5
2374
2375	 pxor	$twres,@tweak[0]		# calculate tweaks^round[last]
2376	aesdec		$rndkey1,$inout4
2377	 pxor	$twres,@tweak[1]
2378	 movdqa	@tweak[0],`16*0`(%rsp)		# put aside tweaks^last round key
2379	aesdec		$rndkey1,$inout5
2380	$movkey		48($key_),$rndkey1
2381	 pxor	$twres,@tweak[2]
2382
2383	aesdec		$rndkey0,$inout0
2384	 pxor	$twres,@tweak[3]
2385	 movdqa	@tweak[1],`16*1`(%rsp)
2386	aesdec		$rndkey0,$inout1
2387	 pxor	$twres,@tweak[4]
2388	 movdqa	@tweak[2],`16*2`(%rsp)
2389	aesdec		$rndkey0,$inout2
2390	aesdec		$rndkey0,$inout3
2391	 pxor	$twres,$twmask
2392	 movdqa	@tweak[4],`16*4`(%rsp)
2393	aesdec		$rndkey0,$inout4
2394	aesdec		$rndkey0,$inout5
2395	$movkey		64($key_),$rndkey0
2396	 movdqa	$twmask,`16*5`(%rsp)
2397	pshufd	\$0x5f,@tweak[5],$twres
2398	jmp	.Lxts_dec_loop6
2399.align	32
2400.Lxts_dec_loop6:
2401	aesdec		$rndkey1,$inout0
2402	aesdec		$rndkey1,$inout1
2403	aesdec		$rndkey1,$inout2
2404	aesdec		$rndkey1,$inout3
2405	aesdec		$rndkey1,$inout4
2406	aesdec		$rndkey1,$inout5
2407	$movkey		-64($key,%rax),$rndkey1
2408	add		\$32,%rax
2409
2410	aesdec		$rndkey0,$inout0
2411	aesdec		$rndkey0,$inout1
2412	aesdec		$rndkey0,$inout2
2413	aesdec		$rndkey0,$inout3
2414	aesdec		$rndkey0,$inout4
2415	aesdec		$rndkey0,$inout5
2416	$movkey		-80($key,%rax),$rndkey0
2417	jnz		.Lxts_dec_loop6
2418
2419	movdqa	(%r8),$twmask			# start calculating next tweak
2420	movdqa	$twres,$twtmp
2421	paddd	$twres,$twres
2422	 aesdec		$rndkey1,$inout0
2423	paddq	@tweak[5],@tweak[5]
2424	psrad	\$31,$twtmp
2425	 aesdec		$rndkey1,$inout1
2426	pand	$twmask,$twtmp
2427	$movkey	($key_),@tweak[0]		# load round[0]
2428	 aesdec		$rndkey1,$inout2
2429	 aesdec		$rndkey1,$inout3
2430	 aesdec		$rndkey1,$inout4
2431	pxor	$twtmp,@tweak[5]
2432	movaps	@tweak[0],@tweak[1]		# copy round[0]
2433	 aesdec		$rndkey1,$inout5
2434	 $movkey	-64($key),$rndkey1
2435
2436	movdqa	$twres,$twtmp
2437	 aesdec		$rndkey0,$inout0
2438	paddd	$twres,$twres
2439	pxor	@tweak[5],@tweak[0]
2440	 aesdec		$rndkey0,$inout1
2441	psrad	\$31,$twtmp
2442	paddq	@tweak[5],@tweak[5]
2443	 aesdec		$rndkey0,$inout2
2444	 aesdec		$rndkey0,$inout3
2445	pand	$twmask,$twtmp
2446	movaps	@tweak[1],@tweak[2]
2447	 aesdec		$rndkey0,$inout4
2448	pxor	$twtmp,@tweak[5]
2449	movdqa	$twres,$twtmp
2450	 aesdec		$rndkey0,$inout5
2451	 $movkey	-48($key),$rndkey0
2452
2453	paddd	$twres,$twres
2454	 aesdec		$rndkey1,$inout0
2455	pxor	@tweak[5],@tweak[1]
2456	psrad	\$31,$twtmp
2457	 aesdec		$rndkey1,$inout1
2458	paddq	@tweak[5],@tweak[5]
2459	pand	$twmask,$twtmp
2460	 aesdec		$rndkey1,$inout2
2461	 aesdec		$rndkey1,$inout3
2462	 movdqa	@tweak[3],`16*3`(%rsp)
2463	pxor	$twtmp,@tweak[5]
2464	 aesdec		$rndkey1,$inout4
2465	movaps	@tweak[2],@tweak[3]
2466	movdqa	$twres,$twtmp
2467	 aesdec		$rndkey1,$inout5
2468	 $movkey	-32($key),$rndkey1
2469
2470	paddd	$twres,$twres
2471	 aesdec		$rndkey0,$inout0
2472	pxor	@tweak[5],@tweak[2]
2473	psrad	\$31,$twtmp
2474	 aesdec		$rndkey0,$inout1
2475	paddq	@tweak[5],@tweak[5]
2476	pand	$twmask,$twtmp
2477	 aesdec		$rndkey0,$inout2
2478	 aesdec		$rndkey0,$inout3
2479	 aesdec		$rndkey0,$inout4
2480	pxor	$twtmp,@tweak[5]
2481	movaps	@tweak[3],@tweak[4]
2482	 aesdec		$rndkey0,$inout5
2483
2484	movdqa	$twres,$rndkey0
2485	paddd	$twres,$twres
2486	 aesdec		$rndkey1,$inout0
2487	pxor	@tweak[5],@tweak[3]
2488	psrad	\$31,$rndkey0
2489	 aesdec		$rndkey1,$inout1
2490	paddq	@tweak[5],@tweak[5]
2491	pand	$twmask,$rndkey0
2492	 aesdec		$rndkey1,$inout2
2493	 aesdec		$rndkey1,$inout3
2494	pxor	$rndkey0,@tweak[5]
2495	$movkey		($key_),$rndkey0
2496	 aesdec		$rndkey1,$inout4
2497	 aesdec		$rndkey1,$inout5
2498	$movkey		16($key_),$rndkey1
2499
2500	pxor	@tweak[5],@tweak[4]
2501	 aesdeclast	`16*0`(%rsp),$inout0
2502	psrad	\$31,$twres
2503	paddq	@tweak[5],@tweak[5]
2504	 aesdeclast	`16*1`(%rsp),$inout1
2505	 aesdeclast	`16*2`(%rsp),$inout2
2506	pand	$twmask,$twres
2507	mov	%r10,%rax			# restore $rounds
2508	 aesdeclast	`16*3`(%rsp),$inout3
2509	 aesdeclast	`16*4`(%rsp),$inout4
2510	 aesdeclast	`16*5`(%rsp),$inout5
2511	pxor	$twres,@tweak[5]
2512
2513	lea	`16*6`($out),$out		# $out+=6*16
2514	movups	$inout0,`-16*6`($out)		# store 6 output blocks
2515	movups	$inout1,`-16*5`($out)
2516	movups	$inout2,`-16*4`($out)
2517	movups	$inout3,`-16*3`($out)
2518	movups	$inout4,`-16*2`($out)
2519	movups	$inout5,`-16*1`($out)
2520	sub	\$16*6,$len
2521	jnc	.Lxts_dec_grandloop		# loop if $len-=6*16 didn't borrow
2522
2523	mov	\$16+96,$rounds
2524	sub	$rnds_,$rounds
2525	mov	$key_,$key			# restore $key
2526	shr	\$4,$rounds			# restore original value
2527
2528.Lxts_dec_short:
2529	# at the point @tweak[0..5] are populated with tweak values
2530	mov	$rounds,$rnds_			# backup $rounds
2531	pxor	$rndkey0,@tweak[0]
2532	pxor	$rndkey0,@tweak[1]
2533	add	\$16*6,$len			# restore real remaining $len
2534	jz	.Lxts_dec_done			# done if ($len==0)
2535
2536	pxor	$rndkey0,@tweak[2]
2537	cmp	\$0x20,$len
2538	jb	.Lxts_dec_one			# $len is 1*16
2539	pxor	$rndkey0,@tweak[3]
2540	je	.Lxts_dec_two			# $len is 2*16
2541
2542	pxor	$rndkey0,@tweak[4]
2543	cmp	\$0x40,$len
2544	jb	.Lxts_dec_three			# $len is 3*16
2545	je	.Lxts_dec_four			# $len is 4*16
2546
2547	movdqu	($inp),$inout0			# $len is 5*16
2548	movdqu	16*1($inp),$inout1
2549	movdqu	16*2($inp),$inout2
2550	pxor	@tweak[0],$inout0
2551	movdqu	16*3($inp),$inout3
2552	pxor	@tweak[1],$inout1
2553	movdqu	16*4($inp),$inout4
2554	lea	16*5($inp),$inp			# $inp+=5*16
2555	pxor	@tweak[2],$inout2
2556	pxor	@tweak[3],$inout3
2557	pxor	@tweak[4],$inout4
2558
2559	call	_aesni_decrypt6
2560
2561	xorps	@tweak[0],$inout0
2562	xorps	@tweak[1],$inout1
2563	xorps	@tweak[2],$inout2
2564	movdqu	$inout0,($out)			# store 5 output blocks
2565	xorps	@tweak[3],$inout3
2566	movdqu	$inout1,16*1($out)
2567	xorps	@tweak[4],$inout4
2568	movdqu	$inout2,16*2($out)
2569	 pxor		$twtmp,$twtmp
2570	movdqu	$inout3,16*3($out)
2571	 pcmpgtd	@tweak[5],$twtmp
2572	movdqu	$inout4,16*4($out)
2573	lea	16*5($out),$out			# $out+=5*16
2574	 pshufd		\$0x13,$twtmp,@tweak[1]	# $twres
2575	and	\$15,$len_
2576	jz	.Lxts_dec_ret
2577
2578	movdqa	@tweak[5],@tweak[0]
2579	paddq	@tweak[5],@tweak[5]		# psllq 1,$tweak
2580	pand	$twmask,@tweak[1]		# isolate carry and residue
2581	pxor	@tweak[5],@tweak[1]
2582	jmp	.Lxts_dec_done2
2583
2584.align	16
2585.Lxts_dec_one:
2586	movups	($inp),$inout0
2587	lea	16*1($inp),$inp			# $inp+=1*16
2588	xorps	@tweak[0],$inout0
2589___
2590	&aesni_generate1("dec",$key,$rounds);
2591$code.=<<___;
2592	xorps	@tweak[0],$inout0
2593	movdqa	@tweak[1],@tweak[0]
2594	movups	$inout0,($out)			# store one output block
2595	movdqa	@tweak[2],@tweak[1]
2596	lea	16*1($out),$out			# $out+=1*16
2597	jmp	.Lxts_dec_done
2598
2599.align	16
2600.Lxts_dec_two:
2601	movups	($inp),$inout0
2602	movups	16($inp),$inout1
2603	lea	32($inp),$inp			# $inp+=2*16
2604	xorps	@tweak[0],$inout0
2605	xorps	@tweak[1],$inout1
2606
2607	call	_aesni_decrypt2
2608
2609	xorps	@tweak[0],$inout0
2610	movdqa	@tweak[2],@tweak[0]
2611	xorps	@tweak[1],$inout1
2612	movdqa	@tweak[3],@tweak[1]
2613	movups	$inout0,($out)			# store 2 output blocks
2614	movups	$inout1,16*1($out)
2615	lea	16*2($out),$out			# $out+=2*16
2616	jmp	.Lxts_dec_done
2617
2618.align	16
2619.Lxts_dec_three:
2620	movups	($inp),$inout0
2621	movups	16*1($inp),$inout1
2622	movups	16*2($inp),$inout2
2623	lea	16*3($inp),$inp			# $inp+=3*16
2624	xorps	@tweak[0],$inout0
2625	xorps	@tweak[1],$inout1
2626	xorps	@tweak[2],$inout2
2627
2628	call	_aesni_decrypt3
2629
2630	xorps	@tweak[0],$inout0
2631	movdqa	@tweak[3],@tweak[0]
2632	xorps	@tweak[1],$inout1
2633	movdqa	@tweak[4],@tweak[1]
2634	xorps	@tweak[2],$inout2
2635	movups	$inout0,($out)			# store 3 output blocks
2636	movups	$inout1,16*1($out)
2637	movups	$inout2,16*2($out)
2638	lea	16*3($out),$out			# $out+=3*16
2639	jmp	.Lxts_dec_done
2640
2641.align	16
2642.Lxts_dec_four:
2643	movups	($inp),$inout0
2644	movups	16*1($inp),$inout1
2645	movups	16*2($inp),$inout2
2646	xorps	@tweak[0],$inout0
2647	movups	16*3($inp),$inout3
2648	lea	16*4($inp),$inp			# $inp+=4*16
2649	xorps	@tweak[1],$inout1
2650	xorps	@tweak[2],$inout2
2651	xorps	@tweak[3],$inout3
2652
2653	call	_aesni_decrypt4
2654
2655	pxor	@tweak[0],$inout0
2656	movdqa	@tweak[4],@tweak[0]
2657	pxor	@tweak[1],$inout1
2658	movdqa	@tweak[5],@tweak[1]
2659	pxor	@tweak[2],$inout2
2660	movdqu	$inout0,($out)			# store 4 output blocks
2661	pxor	@tweak[3],$inout3
2662	movdqu	$inout1,16*1($out)
2663	movdqu	$inout2,16*2($out)
2664	movdqu	$inout3,16*3($out)
2665	lea	16*4($out),$out			# $out+=4*16
2666	jmp	.Lxts_dec_done
2667
2668.align	16
2669.Lxts_dec_done:
2670	and	\$15,$len_			# see if $len%16 is 0
2671	jz	.Lxts_dec_ret
2672.Lxts_dec_done2:
2673	mov	$len_,$len
2674	mov	$key_,$key			# restore $key
2675	mov	$rnds_,$rounds			# restore $rounds
2676
2677	movups	($inp),$inout0
2678	xorps	@tweak[1],$inout0
2679___
2680	&aesni_generate1("dec",$key,$rounds);
2681$code.=<<___;
2682	xorps	@tweak[1],$inout0
2683	movups	$inout0,($out)
2684
2685.Lxts_dec_steal:
2686	movzb	16($inp),%eax			# borrow $rounds ...
2687	movzb	($out),%ecx			# ... and $key
2688	lea	1($inp),$inp
2689	mov	%al,($out)
2690	mov	%cl,16($out)
2691	lea	1($out),$out
2692	sub	\$1,$len
2693	jnz	.Lxts_dec_steal
2694
2695	sub	$len_,$out			# rewind $out
2696	mov	$key_,$key			# restore $key
2697	mov	$rnds_,$rounds			# restore $rounds
2698
2699	movups	($out),$inout0
2700	xorps	@tweak[0],$inout0
2701___
2702	&aesni_generate1("dec",$key,$rounds);
2703$code.=<<___;
2704	xorps	@tweak[0],$inout0
2705	movups	$inout0,($out)
2706
2707.Lxts_dec_ret:
2708	xorps	%xmm0,%xmm0			# clear register bank
2709	pxor	%xmm1,%xmm1
2710	pxor	%xmm2,%xmm2
2711	pxor	%xmm3,%xmm3
2712	pxor	%xmm4,%xmm4
2713	pxor	%xmm5,%xmm5
2714___
2715$code.=<<___ if (!$win64);
2716	pxor	%xmm6,%xmm6
2717	pxor	%xmm7,%xmm7
2718	movaps	%xmm0,0x00(%rsp)		# clear stack
2719	pxor	%xmm8,%xmm8
2720	movaps	%xmm0,0x10(%rsp)
2721	pxor	%xmm9,%xmm9
2722	movaps	%xmm0,0x20(%rsp)
2723	pxor	%xmm10,%xmm10
2724	movaps	%xmm0,0x30(%rsp)
2725	pxor	%xmm11,%xmm11
2726	movaps	%xmm0,0x40(%rsp)
2727	pxor	%xmm12,%xmm12
2728	movaps	%xmm0,0x50(%rsp)
2729	pxor	%xmm13,%xmm13
2730	movaps	%xmm0,0x60(%rsp)
2731	pxor	%xmm14,%xmm14
2732	pxor	%xmm15,%xmm15
2733___
2734$code.=<<___ if ($win64);
2735	movaps	-0xa8(%r11),%xmm6
2736	movaps	%xmm0,-0xa8(%r11)		# clear stack
2737	movaps	-0x98(%r11),%xmm7
2738	movaps	%xmm0,-0x98(%r11)
2739	movaps	-0x88(%r11),%xmm8
2740	movaps	%xmm0,-0x88(%r11)
2741	movaps	-0x78(%r11),%xmm9
2742	movaps	%xmm0,-0x78(%r11)
2743	movaps	-0x68(%r11),%xmm10
2744	movaps	%xmm0,-0x68(%r11)
2745	movaps	-0x58(%r11),%xmm11
2746	movaps	%xmm0,-0x58(%r11)
2747	movaps	-0x48(%r11),%xmm12
2748	movaps	%xmm0,-0x48(%r11)
2749	movaps	-0x38(%r11),%xmm13
2750	movaps	%xmm0,-0x38(%r11)
2751	movaps	-0x28(%r11),%xmm14
2752	movaps	%xmm0,-0x28(%r11)
2753	movaps	-0x18(%r11),%xmm15
2754	movaps	%xmm0,-0x18(%r11)
2755	movaps	%xmm0,0x00(%rsp)
2756	movaps	%xmm0,0x10(%rsp)
2757	movaps	%xmm0,0x20(%rsp)
2758	movaps	%xmm0,0x30(%rsp)
2759	movaps	%xmm0,0x40(%rsp)
2760	movaps	%xmm0,0x50(%rsp)
2761	movaps	%xmm0,0x60(%rsp)
2762___
2763$code.=<<___;
2764	mov	-8(%r11),%rbp
2765.cfi_restore	%rbp
2766	lea	(%r11),%rsp
2767.cfi_def_cfa_register	%rsp
2768.Lxts_dec_epilogue:
2769	ret
2770.cfi_endproc
2771.size	aesni_xts_decrypt,.-aesni_xts_decrypt
2772___
2773}
2774
2775######################################################################
2776# void aesni_ocb_[en|de]crypt(const char *inp, char *out, size_t blocks,
2777#	const AES_KEY *key, unsigned int start_block_num,
2778#	unsigned char offset_i[16], const unsigned char L_[][16],
2779#	unsigned char checksum[16]);
2780#
2781{
2782my @offset=map("%xmm$_",(10..15));
2783my ($checksum,$rndkey0l)=("%xmm8","%xmm9");
2784my ($block_num,$offset_p)=("%r8","%r9");		# 5th and 6th arguments
2785my ($L_p,$checksum_p) = ("%rbx","%rbp");
2786my ($i1,$i3,$i5) = ("%r12","%r13","%r14");
2787my $seventh_arg = $win64 ? 56 : 8;
2788my $blocks = $len;
2789
2790$code.=<<___;
2791.globl	aesni_ocb_encrypt
2792.type	aesni_ocb_encrypt,\@function,6
2793.align	32
2794aesni_ocb_encrypt:
2795.cfi_startproc
2796	endbranch
2797	lea	(%rsp),%rax
2798	push	%rbx
2799.cfi_push	%rbx
2800	push	%rbp
2801.cfi_push	%rbp
2802	push	%r12
2803.cfi_push	%r12
2804	push	%r13
2805.cfi_push	%r13
2806	push	%r14
2807.cfi_push	%r14
2808___
2809$code.=<<___ if ($win64);
2810	lea	-0xa0(%rsp),%rsp
2811	movaps	%xmm6,0x00(%rsp)		# offload everything
2812	movaps	%xmm7,0x10(%rsp)
2813	movaps	%xmm8,0x20(%rsp)
2814	movaps	%xmm9,0x30(%rsp)
2815	movaps	%xmm10,0x40(%rsp)
2816	movaps	%xmm11,0x50(%rsp)
2817	movaps	%xmm12,0x60(%rsp)
2818	movaps	%xmm13,0x70(%rsp)
2819	movaps	%xmm14,0x80(%rsp)
2820	movaps	%xmm15,0x90(%rsp)
2821.Locb_enc_body:
2822___
2823$code.=<<___;
2824	mov	$seventh_arg(%rax),$L_p		# 7th argument
2825	mov	$seventh_arg+8(%rax),$checksum_p# 8th argument
2826
2827	mov	240($key),$rnds_
2828	mov	$key,$key_
2829	shl	\$4,$rnds_
2830	$movkey	($key),$rndkey0l		# round[0]
2831	$movkey	16($key,$rnds_),$rndkey1	# round[last]
2832
2833	movdqu	($offset_p),@offset[5]		# load last offset_i
2834	pxor	$rndkey1,$rndkey0l		# round[0] ^ round[last]
2835	pxor	$rndkey1,@offset[5]		# offset_i ^ round[last]
2836
2837	mov	\$16+32,$rounds
2838	lea	32($key_,$rnds_),$key
2839	$movkey	16($key_),$rndkey1		# round[1]
2840	sub	%r10,%rax			# twisted $rounds
2841	mov	%rax,%r10			# backup twisted $rounds
2842
2843	movdqu	($L_p),@offset[0]		# L_0 for all odd-numbered blocks
2844	movdqu	($checksum_p),$checksum		# load checksum
2845
2846	test	\$1,$block_num			# is first block number odd?
2847	jnz	.Locb_enc_odd
2848
2849	bsf	$block_num,$i1
2850	add	\$1,$block_num
2851	shl	\$4,$i1
2852	movdqu	($L_p,$i1),$inout5		# borrow
2853	movdqu	($inp),$inout0
2854	lea	16($inp),$inp
2855
2856	call	__ocb_encrypt1
2857
2858	movdqa	$inout5,@offset[5]
2859	movups	$inout0,($out)
2860	lea	16($out),$out
2861	sub	\$1,$blocks
2862	jz	.Locb_enc_done
2863
2864.Locb_enc_odd:
2865	lea	1($block_num),$i1		# even-numbered blocks
2866	lea	3($block_num),$i3
2867	lea	5($block_num),$i5
2868	lea	6($block_num),$block_num
2869	bsf	$i1,$i1				# ntz(block)
2870	bsf	$i3,$i3
2871	bsf	$i5,$i5
2872	shl	\$4,$i1				# ntz(block) -> table offset
2873	shl	\$4,$i3
2874	shl	\$4,$i5
2875
2876	sub	\$6,$blocks
2877	jc	.Locb_enc_short
2878	jmp	.Locb_enc_grandloop
2879
2880.align	32
2881.Locb_enc_grandloop:
2882	movdqu	`16*0`($inp),$inout0		# load input
2883	movdqu	`16*1`($inp),$inout1
2884	movdqu	`16*2`($inp),$inout2
2885	movdqu	`16*3`($inp),$inout3
2886	movdqu	`16*4`($inp),$inout4
2887	movdqu	`16*5`($inp),$inout5
2888	lea	`16*6`($inp),$inp
2889
2890	call	__ocb_encrypt6
2891
2892	movups	$inout0,`16*0`($out)		# store output
2893	movups	$inout1,`16*1`($out)
2894	movups	$inout2,`16*2`($out)
2895	movups	$inout3,`16*3`($out)
2896	movups	$inout4,`16*4`($out)
2897	movups	$inout5,`16*5`($out)
2898	lea	`16*6`($out),$out
2899	sub	\$6,$blocks
2900	jnc	.Locb_enc_grandloop
2901
2902.Locb_enc_short:
2903	add	\$6,$blocks
2904	jz	.Locb_enc_done
2905
2906	movdqu	`16*0`($inp),$inout0
2907	cmp	\$2,$blocks
2908	jb	.Locb_enc_one
2909	movdqu	`16*1`($inp),$inout1
2910	je	.Locb_enc_two
2911
2912	movdqu	`16*2`($inp),$inout2
2913	cmp	\$4,$blocks
2914	jb	.Locb_enc_three
2915	movdqu	`16*3`($inp),$inout3
2916	je	.Locb_enc_four
2917
2918	movdqu	`16*4`($inp),$inout4
2919	pxor	$inout5,$inout5
2920
2921	call	__ocb_encrypt6
2922
2923	movdqa	@offset[4],@offset[5]
2924	movups	$inout0,`16*0`($out)
2925	movups	$inout1,`16*1`($out)
2926	movups	$inout2,`16*2`($out)
2927	movups	$inout3,`16*3`($out)
2928	movups	$inout4,`16*4`($out)
2929
2930	jmp	.Locb_enc_done
2931
2932.align	16
2933.Locb_enc_one:
2934	movdqa	@offset[0],$inout5		# borrow
2935
2936	call	__ocb_encrypt1
2937
2938	movdqa	$inout5,@offset[5]
2939	movups	$inout0,`16*0`($out)
2940	jmp	.Locb_enc_done
2941
2942.align	16
2943.Locb_enc_two:
2944	pxor	$inout2,$inout2
2945	pxor	$inout3,$inout3
2946
2947	call	__ocb_encrypt4
2948
2949	movdqa	@offset[1],@offset[5]
2950	movups	$inout0,`16*0`($out)
2951	movups	$inout1,`16*1`($out)
2952
2953	jmp	.Locb_enc_done
2954
2955.align	16
2956.Locb_enc_three:
2957	pxor	$inout3,$inout3
2958
2959	call	__ocb_encrypt4
2960
2961	movdqa	@offset[2],@offset[5]
2962	movups	$inout0,`16*0`($out)
2963	movups	$inout1,`16*1`($out)
2964	movups	$inout2,`16*2`($out)
2965
2966	jmp	.Locb_enc_done
2967
2968.align	16
2969.Locb_enc_four:
2970	call	__ocb_encrypt4
2971
2972	movdqa	@offset[3],@offset[5]
2973	movups	$inout0,`16*0`($out)
2974	movups	$inout1,`16*1`($out)
2975	movups	$inout2,`16*2`($out)
2976	movups	$inout3,`16*3`($out)
2977
2978.Locb_enc_done:
2979	pxor	$rndkey0,@offset[5]		# "remove" round[last]
2980	movdqu	$checksum,($checksum_p)		# store checksum
2981	movdqu	@offset[5],($offset_p)		# store last offset_i
2982
2983	xorps	%xmm0,%xmm0			# clear register bank
2984	pxor	%xmm1,%xmm1
2985	pxor	%xmm2,%xmm2
2986	pxor	%xmm3,%xmm3
2987	pxor	%xmm4,%xmm4
2988	pxor	%xmm5,%xmm5
2989___
2990$code.=<<___ if (!$win64);
2991	pxor	%xmm6,%xmm6
2992	pxor	%xmm7,%xmm7
2993	pxor	%xmm8,%xmm8
2994	pxor	%xmm9,%xmm9
2995	pxor	%xmm10,%xmm10
2996	pxor	%xmm11,%xmm11
2997	pxor	%xmm12,%xmm12
2998	pxor	%xmm13,%xmm13
2999	pxor	%xmm14,%xmm14
3000	pxor	%xmm15,%xmm15
3001	lea	0x28(%rsp),%rax
3002.cfi_def_cfa	%rax,8
3003___
3004$code.=<<___ if ($win64);
3005	movaps	0x00(%rsp),%xmm6
3006	movaps	%xmm0,0x00(%rsp)		# clear stack
3007	movaps	0x10(%rsp),%xmm7
3008	movaps	%xmm0,0x10(%rsp)
3009	movaps	0x20(%rsp),%xmm8
3010	movaps	%xmm0,0x20(%rsp)
3011	movaps	0x30(%rsp),%xmm9
3012	movaps	%xmm0,0x30(%rsp)
3013	movaps	0x40(%rsp),%xmm10
3014	movaps	%xmm0,0x40(%rsp)
3015	movaps	0x50(%rsp),%xmm11
3016	movaps	%xmm0,0x50(%rsp)
3017	movaps	0x60(%rsp),%xmm12
3018	movaps	%xmm0,0x60(%rsp)
3019	movaps	0x70(%rsp),%xmm13
3020	movaps	%xmm0,0x70(%rsp)
3021	movaps	0x80(%rsp),%xmm14
3022	movaps	%xmm0,0x80(%rsp)
3023	movaps	0x90(%rsp),%xmm15
3024	movaps	%xmm0,0x90(%rsp)
3025	lea	0xa0+0x28(%rsp),%rax
3026.Locb_enc_pop:
3027___
3028$code.=<<___;
3029	mov	-40(%rax),%r14
3030.cfi_restore	%r14
3031	mov	-32(%rax),%r13
3032.cfi_restore	%r13
3033	mov	-24(%rax),%r12
3034.cfi_restore	%r12
3035	mov	-16(%rax),%rbp
3036.cfi_restore	%rbp
3037	mov	-8(%rax),%rbx
3038.cfi_restore	%rbx
3039	lea	(%rax),%rsp
3040.cfi_def_cfa_register	%rsp
3041.Locb_enc_epilogue:
3042	ret
3043.cfi_endproc
3044.size	aesni_ocb_encrypt,.-aesni_ocb_encrypt
3045
3046.type	__ocb_encrypt6,\@abi-omnipotent
3047.align	32
3048__ocb_encrypt6:
3049.cfi_startproc
3050	 pxor		$rndkey0l,@offset[5]	# offset_i ^ round[0]
3051	 movdqu		($L_p,$i1),@offset[1]
3052	 movdqa		@offset[0],@offset[2]
3053	 movdqu		($L_p,$i3),@offset[3]
3054	 movdqa		@offset[0],@offset[4]
3055	 pxor		@offset[5],@offset[0]
3056	 movdqu		($L_p,$i5),@offset[5]
3057	 pxor		@offset[0],@offset[1]
3058	pxor		$inout0,$checksum	# accumulate checksum
3059	pxor		@offset[0],$inout0	# input ^ round[0] ^ offset_i
3060	 pxor		@offset[1],@offset[2]
3061	pxor		$inout1,$checksum
3062	pxor		@offset[1],$inout1
3063	 pxor		@offset[2],@offset[3]
3064	pxor		$inout2,$checksum
3065	pxor		@offset[2],$inout2
3066	 pxor		@offset[3],@offset[4]
3067	pxor		$inout3,$checksum
3068	pxor		@offset[3],$inout3
3069	 pxor		@offset[4],@offset[5]
3070	pxor		$inout4,$checksum
3071	pxor		@offset[4],$inout4
3072	pxor		$inout5,$checksum
3073	pxor		@offset[5],$inout5
3074	$movkey		32($key_),$rndkey0
3075
3076	lea		1($block_num),$i1	# even-numbered blocks
3077	lea		3($block_num),$i3
3078	lea		5($block_num),$i5
3079	add		\$6,$block_num
3080	 pxor		$rndkey0l,@offset[0]	# offset_i ^ round[last]
3081	bsf		$i1,$i1			# ntz(block)
3082	bsf		$i3,$i3
3083	bsf		$i5,$i5
3084
3085	aesenc		$rndkey1,$inout0
3086	aesenc		$rndkey1,$inout1
3087	aesenc		$rndkey1,$inout2
3088	aesenc		$rndkey1,$inout3
3089	 pxor		$rndkey0l,@offset[1]
3090	 pxor		$rndkey0l,@offset[2]
3091	aesenc		$rndkey1,$inout4
3092	 pxor		$rndkey0l,@offset[3]
3093	 pxor		$rndkey0l,@offset[4]
3094	aesenc		$rndkey1,$inout5
3095	$movkey		48($key_),$rndkey1
3096	 pxor		$rndkey0l,@offset[5]
3097
3098	aesenc		$rndkey0,$inout0
3099	aesenc		$rndkey0,$inout1
3100	aesenc		$rndkey0,$inout2
3101	aesenc		$rndkey0,$inout3
3102	aesenc		$rndkey0,$inout4
3103	aesenc		$rndkey0,$inout5
3104	$movkey		64($key_),$rndkey0
3105	shl		\$4,$i1			# ntz(block) -> table offset
3106	shl		\$4,$i3
3107	jmp		.Locb_enc_loop6
3108
3109.align	32
3110.Locb_enc_loop6:
3111	aesenc		$rndkey1,$inout0
3112	aesenc		$rndkey1,$inout1
3113	aesenc		$rndkey1,$inout2
3114	aesenc		$rndkey1,$inout3
3115	aesenc		$rndkey1,$inout4
3116	aesenc		$rndkey1,$inout5
3117	$movkey		($key,%rax),$rndkey1
3118	add		\$32,%rax
3119
3120	aesenc		$rndkey0,$inout0
3121	aesenc		$rndkey0,$inout1
3122	aesenc		$rndkey0,$inout2
3123	aesenc		$rndkey0,$inout3
3124	aesenc		$rndkey0,$inout4
3125	aesenc		$rndkey0,$inout5
3126	$movkey		-16($key,%rax),$rndkey0
3127	jnz		.Locb_enc_loop6
3128
3129	aesenc		$rndkey1,$inout0
3130	aesenc		$rndkey1,$inout1
3131	aesenc		$rndkey1,$inout2
3132	aesenc		$rndkey1,$inout3
3133	aesenc		$rndkey1,$inout4
3134	aesenc		$rndkey1,$inout5
3135	$movkey		16($key_),$rndkey1
3136	shl		\$4,$i5
3137
3138	aesenclast	@offset[0],$inout0
3139	movdqu		($L_p),@offset[0]	# L_0 for all odd-numbered blocks
3140	mov		%r10,%rax		# restore twisted rounds
3141	aesenclast	@offset[1],$inout1
3142	aesenclast	@offset[2],$inout2
3143	aesenclast	@offset[3],$inout3
3144	aesenclast	@offset[4],$inout4
3145	aesenclast	@offset[5],$inout5
3146	ret
3147.cfi_endproc
3148.size	__ocb_encrypt6,.-__ocb_encrypt6
3149
3150.type	__ocb_encrypt4,\@abi-omnipotent
3151.align	32
3152__ocb_encrypt4:
3153.cfi_startproc
3154	 pxor		$rndkey0l,@offset[5]	# offset_i ^ round[0]
3155	 movdqu		($L_p,$i1),@offset[1]
3156	 movdqa		@offset[0],@offset[2]
3157	 movdqu		($L_p,$i3),@offset[3]
3158	 pxor		@offset[5],@offset[0]
3159	 pxor		@offset[0],@offset[1]
3160	pxor		$inout0,$checksum	# accumulate checksum
3161	pxor		@offset[0],$inout0	# input ^ round[0] ^ offset_i
3162	 pxor		@offset[1],@offset[2]
3163	pxor		$inout1,$checksum
3164	pxor		@offset[1],$inout1
3165	 pxor		@offset[2],@offset[3]
3166	pxor		$inout2,$checksum
3167	pxor		@offset[2],$inout2
3168	pxor		$inout3,$checksum
3169	pxor		@offset[3],$inout3
3170	$movkey		32($key_),$rndkey0
3171
3172	 pxor		$rndkey0l,@offset[0]	# offset_i ^ round[last]
3173	 pxor		$rndkey0l,@offset[1]
3174	 pxor		$rndkey0l,@offset[2]
3175	 pxor		$rndkey0l,@offset[3]
3176
3177	aesenc		$rndkey1,$inout0
3178	aesenc		$rndkey1,$inout1
3179	aesenc		$rndkey1,$inout2
3180	aesenc		$rndkey1,$inout3
3181	$movkey		48($key_),$rndkey1
3182
3183	aesenc		$rndkey0,$inout0
3184	aesenc		$rndkey0,$inout1
3185	aesenc		$rndkey0,$inout2
3186	aesenc		$rndkey0,$inout3
3187	$movkey		64($key_),$rndkey0
3188	jmp		.Locb_enc_loop4
3189
3190.align	32
3191.Locb_enc_loop4:
3192	aesenc		$rndkey1,$inout0
3193	aesenc		$rndkey1,$inout1
3194	aesenc		$rndkey1,$inout2
3195	aesenc		$rndkey1,$inout3
3196	$movkey		($key,%rax),$rndkey1
3197	add		\$32,%rax
3198
3199	aesenc		$rndkey0,$inout0
3200	aesenc		$rndkey0,$inout1
3201	aesenc		$rndkey0,$inout2
3202	aesenc		$rndkey0,$inout3
3203	$movkey		-16($key,%rax),$rndkey0
3204	jnz		.Locb_enc_loop4
3205
3206	aesenc		$rndkey1,$inout0
3207	aesenc		$rndkey1,$inout1
3208	aesenc		$rndkey1,$inout2
3209	aesenc		$rndkey1,$inout3
3210	$movkey		16($key_),$rndkey1
3211	mov		%r10,%rax		# restore twisted rounds
3212
3213	aesenclast	@offset[0],$inout0
3214	aesenclast	@offset[1],$inout1
3215	aesenclast	@offset[2],$inout2
3216	aesenclast	@offset[3],$inout3
3217	ret
3218.cfi_endproc
3219.size	__ocb_encrypt4,.-__ocb_encrypt4
3220
3221.type	__ocb_encrypt1,\@abi-omnipotent
3222.align	32
3223__ocb_encrypt1:
3224.cfi_startproc
3225	 pxor		@offset[5],$inout5	# offset_i
3226	 pxor		$rndkey0l,$inout5	# offset_i ^ round[0]
3227	pxor		$inout0,$checksum	# accumulate checksum
3228	pxor		$inout5,$inout0		# input ^ round[0] ^ offset_i
3229	$movkey		32($key_),$rndkey0
3230
3231	aesenc		$rndkey1,$inout0
3232	$movkey		48($key_),$rndkey1
3233	pxor		$rndkey0l,$inout5	# offset_i ^ round[last]
3234
3235	aesenc		$rndkey0,$inout0
3236	$movkey		64($key_),$rndkey0
3237	jmp		.Locb_enc_loop1
3238
3239.align	32
3240.Locb_enc_loop1:
3241	aesenc		$rndkey1,$inout0
3242	$movkey		($key,%rax),$rndkey1
3243	add		\$32,%rax
3244
3245	aesenc		$rndkey0,$inout0
3246	$movkey		-16($key,%rax),$rndkey0
3247	jnz		.Locb_enc_loop1
3248
3249	aesenc		$rndkey1,$inout0
3250	$movkey		16($key_),$rndkey1	# redundant in tail
3251	mov		%r10,%rax		# restore twisted rounds
3252
3253	aesenclast	$inout5,$inout0
3254	ret
3255.cfi_endproc
3256.size	__ocb_encrypt1,.-__ocb_encrypt1
3257
3258.globl	aesni_ocb_decrypt
3259.type	aesni_ocb_decrypt,\@function,6
3260.align	32
3261aesni_ocb_decrypt:
3262.cfi_startproc
3263	endbranch
3264	lea	(%rsp),%rax
3265	push	%rbx
3266.cfi_push	%rbx
3267	push	%rbp
3268.cfi_push	%rbp
3269	push	%r12
3270.cfi_push	%r12
3271	push	%r13
3272.cfi_push	%r13
3273	push	%r14
3274.cfi_push	%r14
3275___
3276$code.=<<___ if ($win64);
3277	lea	-0xa0(%rsp),%rsp
3278	movaps	%xmm6,0x00(%rsp)		# offload everything
3279	movaps	%xmm7,0x10(%rsp)
3280	movaps	%xmm8,0x20(%rsp)
3281	movaps	%xmm9,0x30(%rsp)
3282	movaps	%xmm10,0x40(%rsp)
3283	movaps	%xmm11,0x50(%rsp)
3284	movaps	%xmm12,0x60(%rsp)
3285	movaps	%xmm13,0x70(%rsp)
3286	movaps	%xmm14,0x80(%rsp)
3287	movaps	%xmm15,0x90(%rsp)
3288.Locb_dec_body:
3289___
3290$code.=<<___;
3291	mov	$seventh_arg(%rax),$L_p		# 7th argument
3292	mov	$seventh_arg+8(%rax),$checksum_p# 8th argument
3293
3294	mov	240($key),$rnds_
3295	mov	$key,$key_
3296	shl	\$4,$rnds_
3297	$movkey	($key),$rndkey0l		# round[0]
3298	$movkey	16($key,$rnds_),$rndkey1	# round[last]
3299
3300	movdqu	($offset_p),@offset[5]		# load last offset_i
3301	pxor	$rndkey1,$rndkey0l		# round[0] ^ round[last]
3302	pxor	$rndkey1,@offset[5]		# offset_i ^ round[last]
3303
3304	mov	\$16+32,$rounds
3305	lea	32($key_,$rnds_),$key
3306	$movkey	16($key_),$rndkey1		# round[1]
3307	sub	%r10,%rax			# twisted $rounds
3308	mov	%rax,%r10			# backup twisted $rounds
3309
3310	movdqu	($L_p),@offset[0]		# L_0 for all odd-numbered blocks
3311	movdqu	($checksum_p),$checksum		# load checksum
3312
3313	test	\$1,$block_num			# is first block number odd?
3314	jnz	.Locb_dec_odd
3315
3316	bsf	$block_num,$i1
3317	add	\$1,$block_num
3318	shl	\$4,$i1
3319	movdqu	($L_p,$i1),$inout5		# borrow
3320	movdqu	($inp),$inout0
3321	lea	16($inp),$inp
3322
3323	call	__ocb_decrypt1
3324
3325	movdqa	$inout5,@offset[5]
3326	movups	$inout0,($out)
3327	xorps	$inout0,$checksum		# accumulate checksum
3328	lea	16($out),$out
3329	sub	\$1,$blocks
3330	jz	.Locb_dec_done
3331
3332.Locb_dec_odd:
3333	lea	1($block_num),$i1		# even-numbered blocks
3334	lea	3($block_num),$i3
3335	lea	5($block_num),$i5
3336	lea	6($block_num),$block_num
3337	bsf	$i1,$i1				# ntz(block)
3338	bsf	$i3,$i3
3339	bsf	$i5,$i5
3340	shl	\$4,$i1				# ntz(block) -> table offset
3341	shl	\$4,$i3
3342	shl	\$4,$i5
3343
3344	sub	\$6,$blocks
3345	jc	.Locb_dec_short
3346	jmp	.Locb_dec_grandloop
3347
3348.align	32
3349.Locb_dec_grandloop:
3350	movdqu	`16*0`($inp),$inout0		# load input
3351	movdqu	`16*1`($inp),$inout1
3352	movdqu	`16*2`($inp),$inout2
3353	movdqu	`16*3`($inp),$inout3
3354	movdqu	`16*4`($inp),$inout4
3355	movdqu	`16*5`($inp),$inout5
3356	lea	`16*6`($inp),$inp
3357
3358	call	__ocb_decrypt6
3359
3360	movups	$inout0,`16*0`($out)		# store output
3361	pxor	$inout0,$checksum		# accumulate checksum
3362	movups	$inout1,`16*1`($out)
3363	pxor	$inout1,$checksum
3364	movups	$inout2,`16*2`($out)
3365	pxor	$inout2,$checksum
3366	movups	$inout3,`16*3`($out)
3367	pxor	$inout3,$checksum
3368	movups	$inout4,`16*4`($out)
3369	pxor	$inout4,$checksum
3370	movups	$inout5,`16*5`($out)
3371	pxor	$inout5,$checksum
3372	lea	`16*6`($out),$out
3373	sub	\$6,$blocks
3374	jnc	.Locb_dec_grandloop
3375
3376.Locb_dec_short:
3377	add	\$6,$blocks
3378	jz	.Locb_dec_done
3379
3380	movdqu	`16*0`($inp),$inout0
3381	cmp	\$2,$blocks
3382	jb	.Locb_dec_one
3383	movdqu	`16*1`($inp),$inout1
3384	je	.Locb_dec_two
3385
3386	movdqu	`16*2`($inp),$inout2
3387	cmp	\$4,$blocks
3388	jb	.Locb_dec_three
3389	movdqu	`16*3`($inp),$inout3
3390	je	.Locb_dec_four
3391
3392	movdqu	`16*4`($inp),$inout4
3393	pxor	$inout5,$inout5
3394
3395	call	__ocb_decrypt6
3396
3397	movdqa	@offset[4],@offset[5]
3398	movups	$inout0,`16*0`($out)		# store output
3399	pxor	$inout0,$checksum		# accumulate checksum
3400	movups	$inout1,`16*1`($out)
3401	pxor	$inout1,$checksum
3402	movups	$inout2,`16*2`($out)
3403	pxor	$inout2,$checksum
3404	movups	$inout3,`16*3`($out)
3405	pxor	$inout3,$checksum
3406	movups	$inout4,`16*4`($out)
3407	pxor	$inout4,$checksum
3408
3409	jmp	.Locb_dec_done
3410
3411.align	16
3412.Locb_dec_one:
3413	movdqa	@offset[0],$inout5		# borrow
3414
3415	call	__ocb_decrypt1
3416
3417	movdqa	$inout5,@offset[5]
3418	movups	$inout0,`16*0`($out)		# store output
3419	xorps	$inout0,$checksum		# accumulate checksum
3420	jmp	.Locb_dec_done
3421
3422.align	16
3423.Locb_dec_two:
3424	pxor	$inout2,$inout2
3425	pxor	$inout3,$inout3
3426
3427	call	__ocb_decrypt4
3428
3429	movdqa	@offset[1],@offset[5]
3430	movups	$inout0,`16*0`($out)		# store output
3431	xorps	$inout0,$checksum		# accumulate checksum
3432	movups	$inout1,`16*1`($out)
3433	xorps	$inout1,$checksum
3434
3435	jmp	.Locb_dec_done
3436
3437.align	16
3438.Locb_dec_three:
3439	pxor	$inout3,$inout3
3440
3441	call	__ocb_decrypt4
3442
3443	movdqa	@offset[2],@offset[5]
3444	movups	$inout0,`16*0`($out)		# store output
3445	xorps	$inout0,$checksum		# accumulate checksum
3446	movups	$inout1,`16*1`($out)
3447	xorps	$inout1,$checksum
3448	movups	$inout2,`16*2`($out)
3449	xorps	$inout2,$checksum
3450
3451	jmp	.Locb_dec_done
3452
3453.align	16
3454.Locb_dec_four:
3455	call	__ocb_decrypt4
3456
3457	movdqa	@offset[3],@offset[5]
3458	movups	$inout0,`16*0`($out)		# store output
3459	pxor	$inout0,$checksum		# accumulate checksum
3460	movups	$inout1,`16*1`($out)
3461	pxor	$inout1,$checksum
3462	movups	$inout2,`16*2`($out)
3463	pxor	$inout2,$checksum
3464	movups	$inout3,`16*3`($out)
3465	pxor	$inout3,$checksum
3466
3467.Locb_dec_done:
3468	pxor	$rndkey0,@offset[5]		# "remove" round[last]
3469	movdqu	$checksum,($checksum_p)		# store checksum
3470	movdqu	@offset[5],($offset_p)		# store last offset_i
3471
3472	xorps	%xmm0,%xmm0			# clear register bank
3473	pxor	%xmm1,%xmm1
3474	pxor	%xmm2,%xmm2
3475	pxor	%xmm3,%xmm3
3476	pxor	%xmm4,%xmm4
3477	pxor	%xmm5,%xmm5
3478___
3479$code.=<<___ if (!$win64);
3480	pxor	%xmm6,%xmm6
3481	pxor	%xmm7,%xmm7
3482	pxor	%xmm8,%xmm8
3483	pxor	%xmm9,%xmm9
3484	pxor	%xmm10,%xmm10
3485	pxor	%xmm11,%xmm11
3486	pxor	%xmm12,%xmm12
3487	pxor	%xmm13,%xmm13
3488	pxor	%xmm14,%xmm14
3489	pxor	%xmm15,%xmm15
3490	lea	0x28(%rsp),%rax
3491.cfi_def_cfa	%rax,8
3492___
3493$code.=<<___ if ($win64);
3494	movaps	0x00(%rsp),%xmm6
3495	movaps	%xmm0,0x00(%rsp)		# clear stack
3496	movaps	0x10(%rsp),%xmm7
3497	movaps	%xmm0,0x10(%rsp)
3498	movaps	0x20(%rsp),%xmm8
3499	movaps	%xmm0,0x20(%rsp)
3500	movaps	0x30(%rsp),%xmm9
3501	movaps	%xmm0,0x30(%rsp)
3502	movaps	0x40(%rsp),%xmm10
3503	movaps	%xmm0,0x40(%rsp)
3504	movaps	0x50(%rsp),%xmm11
3505	movaps	%xmm0,0x50(%rsp)
3506	movaps	0x60(%rsp),%xmm12
3507	movaps	%xmm0,0x60(%rsp)
3508	movaps	0x70(%rsp),%xmm13
3509	movaps	%xmm0,0x70(%rsp)
3510	movaps	0x80(%rsp),%xmm14
3511	movaps	%xmm0,0x80(%rsp)
3512	movaps	0x90(%rsp),%xmm15
3513	movaps	%xmm0,0x90(%rsp)
3514	lea	0xa0+0x28(%rsp),%rax
3515.Locb_dec_pop:
3516___
3517$code.=<<___;
3518	mov	-40(%rax),%r14
3519.cfi_restore	%r14
3520	mov	-32(%rax),%r13
3521.cfi_restore	%r13
3522	mov	-24(%rax),%r12
3523.cfi_restore	%r12
3524	mov	-16(%rax),%rbp
3525.cfi_restore	%rbp
3526	mov	-8(%rax),%rbx
3527.cfi_restore	%rbx
3528	lea	(%rax),%rsp
3529.cfi_def_cfa_register	%rsp
3530.Locb_dec_epilogue:
3531	ret
3532.cfi_endproc
3533.size	aesni_ocb_decrypt,.-aesni_ocb_decrypt
3534
3535.type	__ocb_decrypt6,\@abi-omnipotent
3536.align	32
3537__ocb_decrypt6:
3538.cfi_startproc
3539	 pxor		$rndkey0l,@offset[5]	# offset_i ^ round[0]
3540	 movdqu		($L_p,$i1),@offset[1]
3541	 movdqa		@offset[0],@offset[2]
3542	 movdqu		($L_p,$i3),@offset[3]
3543	 movdqa		@offset[0],@offset[4]
3544	 pxor		@offset[5],@offset[0]
3545	 movdqu		($L_p,$i5),@offset[5]
3546	 pxor		@offset[0],@offset[1]
3547	pxor		@offset[0],$inout0	# input ^ round[0] ^ offset_i
3548	 pxor		@offset[1],@offset[2]
3549	pxor		@offset[1],$inout1
3550	 pxor		@offset[2],@offset[3]
3551	pxor		@offset[2],$inout2
3552	 pxor		@offset[3],@offset[4]
3553	pxor		@offset[3],$inout3
3554	 pxor		@offset[4],@offset[5]
3555	pxor		@offset[4],$inout4
3556	pxor		@offset[5],$inout5
3557	$movkey		32($key_),$rndkey0
3558
3559	lea		1($block_num),$i1	# even-numbered blocks
3560	lea		3($block_num),$i3
3561	lea		5($block_num),$i5
3562	add		\$6,$block_num
3563	 pxor		$rndkey0l,@offset[0]	# offset_i ^ round[last]
3564	bsf		$i1,$i1			# ntz(block)
3565	bsf		$i3,$i3
3566	bsf		$i5,$i5
3567
3568	aesdec		$rndkey1,$inout0
3569	aesdec		$rndkey1,$inout1
3570	aesdec		$rndkey1,$inout2
3571	aesdec		$rndkey1,$inout3
3572	 pxor		$rndkey0l,@offset[1]
3573	 pxor		$rndkey0l,@offset[2]
3574	aesdec		$rndkey1,$inout4
3575	 pxor		$rndkey0l,@offset[3]
3576	 pxor		$rndkey0l,@offset[4]
3577	aesdec		$rndkey1,$inout5
3578	$movkey		48($key_),$rndkey1
3579	 pxor		$rndkey0l,@offset[5]
3580
3581	aesdec		$rndkey0,$inout0
3582	aesdec		$rndkey0,$inout1
3583	aesdec		$rndkey0,$inout2
3584	aesdec		$rndkey0,$inout3
3585	aesdec		$rndkey0,$inout4
3586	aesdec		$rndkey0,$inout5
3587	$movkey		64($key_),$rndkey0
3588	shl		\$4,$i1			# ntz(block) -> table offset
3589	shl		\$4,$i3
3590	jmp		.Locb_dec_loop6
3591
3592.align	32
3593.Locb_dec_loop6:
3594	aesdec		$rndkey1,$inout0
3595	aesdec		$rndkey1,$inout1
3596	aesdec		$rndkey1,$inout2
3597	aesdec		$rndkey1,$inout3
3598	aesdec		$rndkey1,$inout4
3599	aesdec		$rndkey1,$inout5
3600	$movkey		($key,%rax),$rndkey1
3601	add		\$32,%rax
3602
3603	aesdec		$rndkey0,$inout0
3604	aesdec		$rndkey0,$inout1
3605	aesdec		$rndkey0,$inout2
3606	aesdec		$rndkey0,$inout3
3607	aesdec		$rndkey0,$inout4
3608	aesdec		$rndkey0,$inout5
3609	$movkey		-16($key,%rax),$rndkey0
3610	jnz		.Locb_dec_loop6
3611
3612	aesdec		$rndkey1,$inout0
3613	aesdec		$rndkey1,$inout1
3614	aesdec		$rndkey1,$inout2
3615	aesdec		$rndkey1,$inout3
3616	aesdec		$rndkey1,$inout4
3617	aesdec		$rndkey1,$inout5
3618	$movkey		16($key_),$rndkey1
3619	shl		\$4,$i5
3620
3621	aesdeclast	@offset[0],$inout0
3622	movdqu		($L_p),@offset[0]	# L_0 for all odd-numbered blocks
3623	mov		%r10,%rax		# restore twisted rounds
3624	aesdeclast	@offset[1],$inout1
3625	aesdeclast	@offset[2],$inout2
3626	aesdeclast	@offset[3],$inout3
3627	aesdeclast	@offset[4],$inout4
3628	aesdeclast	@offset[5],$inout5
3629	ret
3630.cfi_endproc
3631.size	__ocb_decrypt6,.-__ocb_decrypt6
3632
3633.type	__ocb_decrypt4,\@abi-omnipotent
3634.align	32
3635__ocb_decrypt4:
3636.cfi_startproc
3637	 pxor		$rndkey0l,@offset[5]	# offset_i ^ round[0]
3638	 movdqu		($L_p,$i1),@offset[1]
3639	 movdqa		@offset[0],@offset[2]
3640	 movdqu		($L_p,$i3),@offset[3]
3641	 pxor		@offset[5],@offset[0]
3642	 pxor		@offset[0],@offset[1]
3643	pxor		@offset[0],$inout0	# input ^ round[0] ^ offset_i
3644	 pxor		@offset[1],@offset[2]
3645	pxor		@offset[1],$inout1
3646	 pxor		@offset[2],@offset[3]
3647	pxor		@offset[2],$inout2
3648	pxor		@offset[3],$inout3
3649	$movkey		32($key_),$rndkey0
3650
3651	 pxor		$rndkey0l,@offset[0]	# offset_i ^ round[last]
3652	 pxor		$rndkey0l,@offset[1]
3653	 pxor		$rndkey0l,@offset[2]
3654	 pxor		$rndkey0l,@offset[3]
3655
3656	aesdec		$rndkey1,$inout0
3657	aesdec		$rndkey1,$inout1
3658	aesdec		$rndkey1,$inout2
3659	aesdec		$rndkey1,$inout3
3660	$movkey		48($key_),$rndkey1
3661
3662	aesdec		$rndkey0,$inout0
3663	aesdec		$rndkey0,$inout1
3664	aesdec		$rndkey0,$inout2
3665	aesdec		$rndkey0,$inout3
3666	$movkey		64($key_),$rndkey0
3667	jmp		.Locb_dec_loop4
3668
3669.align	32
3670.Locb_dec_loop4:
3671	aesdec		$rndkey1,$inout0
3672	aesdec		$rndkey1,$inout1
3673	aesdec		$rndkey1,$inout2
3674	aesdec		$rndkey1,$inout3
3675	$movkey		($key,%rax),$rndkey1
3676	add		\$32,%rax
3677
3678	aesdec		$rndkey0,$inout0
3679	aesdec		$rndkey0,$inout1
3680	aesdec		$rndkey0,$inout2
3681	aesdec		$rndkey0,$inout3
3682	$movkey		-16($key,%rax),$rndkey0
3683	jnz		.Locb_dec_loop4
3684
3685	aesdec		$rndkey1,$inout0
3686	aesdec		$rndkey1,$inout1
3687	aesdec		$rndkey1,$inout2
3688	aesdec		$rndkey1,$inout3
3689	$movkey		16($key_),$rndkey1
3690	mov		%r10,%rax		# restore twisted rounds
3691
3692	aesdeclast	@offset[0],$inout0
3693	aesdeclast	@offset[1],$inout1
3694	aesdeclast	@offset[2],$inout2
3695	aesdeclast	@offset[3],$inout3
3696	ret
3697.cfi_endproc
3698.size	__ocb_decrypt4,.-__ocb_decrypt4
3699
3700.type	__ocb_decrypt1,\@abi-omnipotent
3701.align	32
3702__ocb_decrypt1:
3703.cfi_startproc
3704	 pxor		@offset[5],$inout5	# offset_i
3705	 pxor		$rndkey0l,$inout5	# offset_i ^ round[0]
3706	pxor		$inout5,$inout0		# input ^ round[0] ^ offset_i
3707	$movkey		32($key_),$rndkey0
3708
3709	aesdec		$rndkey1,$inout0
3710	$movkey		48($key_),$rndkey1
3711	pxor		$rndkey0l,$inout5	# offset_i ^ round[last]
3712
3713	aesdec		$rndkey0,$inout0
3714	$movkey		64($key_),$rndkey0
3715	jmp		.Locb_dec_loop1
3716
3717.align	32
3718.Locb_dec_loop1:
3719	aesdec		$rndkey1,$inout0
3720	$movkey		($key,%rax),$rndkey1
3721	add		\$32,%rax
3722
3723	aesdec		$rndkey0,$inout0
3724	$movkey		-16($key,%rax),$rndkey0
3725	jnz		.Locb_dec_loop1
3726
3727	aesdec		$rndkey1,$inout0
3728	$movkey		16($key_),$rndkey1	# redundant in tail
3729	mov		%r10,%rax		# restore twisted rounds
3730
3731	aesdeclast	$inout5,$inout0
3732	ret
3733.cfi_endproc
3734.size	__ocb_decrypt1,.-__ocb_decrypt1
3735___
3736} }}
3737
3738########################################################################
3739# void $PREFIX_cbc_encrypt (const void *inp, void *out,
3740#			    size_t length, const AES_KEY *key,
3741#			    unsigned char *ivp,const int enc);
3742{
3743my $frame_size = 0x10 + ($win64?0xa0:0);	# used in decrypt
3744my ($iv,$in0,$in1,$in2,$in3,$in4)=map("%xmm$_",(10..15));
3745
3746$code.=<<___;
3747.globl	${PREFIX}_cbc_encrypt
3748.type	${PREFIX}_cbc_encrypt,\@function,6
3749.align	16
3750${PREFIX}_cbc_encrypt:
3751.cfi_startproc
3752	endbranch
3753	test	$len,$len		# check length
3754	jz	.Lcbc_ret
3755
3756	mov	240($key),$rnds_	# key->rounds
3757	mov	$key,$key_		# backup $key
3758	test	%r9d,%r9d		# 6th argument
3759	jz	.Lcbc_decrypt
3760#--------------------------- CBC ENCRYPT ------------------------------#
3761	movups	($ivp),$inout0		# load iv as initial state
3762	mov	$rnds_,$rounds
3763	cmp	\$16,$len
3764	jb	.Lcbc_enc_tail
3765	sub	\$16,$len
3766	jmp	.Lcbc_enc_loop
3767.align	16
3768.Lcbc_enc_loop:
3769	movups	($inp),$inout1		# load input
3770	lea	16($inp),$inp
3771	#xorps	$inout1,$inout0
3772___
3773	&aesni_generate1("enc",$key,$rounds,$inout0,$inout1);
3774$code.=<<___;
3775	mov	$rnds_,$rounds		# restore $rounds
3776	mov	$key_,$key		# restore $key
3777	movups	$inout0,0($out)		# store output
3778	lea	16($out),$out
3779	sub	\$16,$len
3780	jnc	.Lcbc_enc_loop
3781	add	\$16,$len
3782	jnz	.Lcbc_enc_tail
3783	 pxor	$rndkey0,$rndkey0	# clear register bank
3784	 pxor	$rndkey1,$rndkey1
3785	movups	$inout0,($ivp)
3786	 pxor	$inout0,$inout0
3787	 pxor	$inout1,$inout1
3788	jmp	.Lcbc_ret
3789
3790.Lcbc_enc_tail:
3791	mov	$len,%rcx	# zaps $key
3792	xchg	$inp,$out	# $inp is %rsi and $out is %rdi now
3793	.long	0x9066A4F3	# rep movsb
3794	mov	\$16,%ecx	# zero tail
3795	sub	$len,%rcx
3796	xor	%eax,%eax
3797	.long	0x9066AAF3	# rep stosb
3798	lea	-16(%rdi),%rdi	# rewind $out by 1 block
3799	mov	$rnds_,$rounds	# restore $rounds
3800	mov	%rdi,%rsi	# $inp and $out are the same
3801	mov	$key_,$key	# restore $key
3802	xor	$len,$len	# len=16
3803	jmp	.Lcbc_enc_loop	# one more spin
3804#--------------------------- CBC DECRYPT ------------------------------#
3805.align	16
3806.Lcbc_decrypt:
3807	cmp	\$16,$len
3808	jne	.Lcbc_decrypt_bulk
3809
3810	# handle single block without allocating stack frame,
3811	# useful in ciphertext stealing mode
3812	movdqu	($inp),$inout0		# load input
3813	movdqu	($ivp),$inout1		# load iv
3814	movdqa	$inout0,$inout2		# future iv
3815___
3816	&aesni_generate1("dec",$key,$rnds_);
3817$code.=<<___;
3818	 pxor	$rndkey0,$rndkey0	# clear register bank
3819	 pxor	$rndkey1,$rndkey1
3820	movdqu	$inout2,($ivp)		# store iv
3821	xorps	$inout1,$inout0		# ^=iv
3822	 pxor	$inout1,$inout1
3823	movups	$inout0,($out)		# store output
3824	 pxor	$inout0,$inout0
3825	jmp	.Lcbc_ret
3826.align	16
3827.Lcbc_decrypt_bulk:
3828	lea	(%rsp),%r11		# frame pointer
3829.cfi_def_cfa_register	%r11
3830	push	%rbp
3831.cfi_push	%rbp
3832	sub	\$$frame_size,%rsp
3833	and	\$-16,%rsp	# Linux kernel stack can be incorrectly seeded
3834___
3835$code.=<<___ if ($win64);
3836	movaps	%xmm6,0x10(%rsp)
3837	movaps	%xmm7,0x20(%rsp)
3838	movaps	%xmm8,0x30(%rsp)
3839	movaps	%xmm9,0x40(%rsp)
3840	movaps	%xmm10,0x50(%rsp)
3841	movaps	%xmm11,0x60(%rsp)
3842	movaps	%xmm12,0x70(%rsp)
3843	movaps	%xmm13,0x80(%rsp)
3844	movaps	%xmm14,0x90(%rsp)
3845	movaps	%xmm15,0xa0(%rsp)
3846.Lcbc_decrypt_body:
3847___
3848
3849my $inp_=$key_="%rbp";			# reassign $key_
3850
3851$code.=<<___;
3852	mov	$key,$key_		# [re-]backup $key [after reassignment]
3853	movups	($ivp),$iv
3854	mov	$rnds_,$rounds
3855	cmp	\$0x50,$len
3856	jbe	.Lcbc_dec_tail
3857
3858	$movkey	($key),$rndkey0
3859	movdqu	0x00($inp),$inout0	# load input
3860	movdqu	0x10($inp),$inout1
3861	movdqa	$inout0,$in0
3862	movdqu	0x20($inp),$inout2
3863	movdqa	$inout1,$in1
3864	movdqu	0x30($inp),$inout3
3865	movdqa	$inout2,$in2
3866	movdqu	0x40($inp),$inout4
3867	movdqa	$inout3,$in3
3868	movdqu	0x50($inp),$inout5
3869	movdqa	$inout4,$in4
3870	mov	OPENSSL_ia32cap_P+4(%rip),%r9d
3871	cmp	\$0x70,$len
3872	jbe	.Lcbc_dec_six_or_seven
3873
3874	and	\$`1<<26|1<<22`,%r9d	# isolate XSAVE+MOVBE
3875	sub	\$0x50,$len		# $len is biased by -5*16
3876	cmp	\$`1<<22`,%r9d		# check for MOVBE without XSAVE
3877	je	.Lcbc_dec_loop6_enter	# [which denotes Atom Silvermont]
3878	sub	\$0x20,$len		# $len is biased by -7*16
3879	lea	0x70($key),$key		# size optimization
3880	jmp	.Lcbc_dec_loop8_enter
3881.align	16
3882.Lcbc_dec_loop8:
3883	movups	$inout7,($out)
3884	lea	0x10($out),$out
3885.Lcbc_dec_loop8_enter:
3886	movdqu		0x60($inp),$inout6
3887	pxor		$rndkey0,$inout0
3888	movdqu		0x70($inp),$inout7
3889	pxor		$rndkey0,$inout1
3890	$movkey		0x10-0x70($key),$rndkey1
3891	pxor		$rndkey0,$inout2
3892	mov		\$-1,$inp_
3893	cmp		\$0x70,$len	# is there at least 0x60 bytes ahead?
3894	pxor		$rndkey0,$inout3
3895	pxor		$rndkey0,$inout4
3896	pxor		$rndkey0,$inout5
3897	pxor		$rndkey0,$inout6
3898
3899	aesdec		$rndkey1,$inout0
3900	pxor		$rndkey0,$inout7
3901	$movkey		0x20-0x70($key),$rndkey0
3902	aesdec		$rndkey1,$inout1
3903	aesdec		$rndkey1,$inout2
3904	aesdec		$rndkey1,$inout3
3905	aesdec		$rndkey1,$inout4
3906	aesdec		$rndkey1,$inout5
3907	aesdec		$rndkey1,$inout6
3908	adc		\$0,$inp_
3909	and		\$128,$inp_
3910	aesdec		$rndkey1,$inout7
3911	add		$inp,$inp_
3912	$movkey		0x30-0x70($key),$rndkey1
3913___
3914for($i=1;$i<12;$i++) {
3915my $rndkeyx = ($i&1)?$rndkey0:$rndkey1;
3916$code.=<<___	if ($i==7);
3917	cmp		\$11,$rounds
3918___
3919$code.=<<___;
3920	aesdec		$rndkeyx,$inout0
3921	aesdec		$rndkeyx,$inout1
3922	aesdec		$rndkeyx,$inout2
3923	aesdec		$rndkeyx,$inout3
3924	aesdec		$rndkeyx,$inout4
3925	aesdec		$rndkeyx,$inout5
3926	aesdec		$rndkeyx,$inout6
3927	aesdec		$rndkeyx,$inout7
3928	$movkey		`0x30+0x10*$i`-0x70($key),$rndkeyx
3929___
3930$code.=<<___	if ($i<6 || (!($i&1) && $i>7));
3931	nop
3932___
3933$code.=<<___	if ($i==7);
3934	jb		.Lcbc_dec_done
3935___
3936$code.=<<___	if ($i==9);
3937	je		.Lcbc_dec_done
3938___
3939$code.=<<___	if ($i==11);
3940	jmp		.Lcbc_dec_done
3941___
3942}
3943$code.=<<___;
3944.align	16
3945.Lcbc_dec_done:
3946	aesdec		$rndkey1,$inout0
3947	aesdec		$rndkey1,$inout1
3948	pxor		$rndkey0,$iv
3949	pxor		$rndkey0,$in0
3950	aesdec		$rndkey1,$inout2
3951	aesdec		$rndkey1,$inout3
3952	pxor		$rndkey0,$in1
3953	pxor		$rndkey0,$in2
3954	aesdec		$rndkey1,$inout4
3955	aesdec		$rndkey1,$inout5
3956	pxor		$rndkey0,$in3
3957	pxor		$rndkey0,$in4
3958	aesdec		$rndkey1,$inout6
3959	aesdec		$rndkey1,$inout7
3960	movdqu		0x50($inp),$rndkey1
3961
3962	aesdeclast	$iv,$inout0
3963	movdqu		0x60($inp),$iv		# borrow $iv
3964	pxor		$rndkey0,$rndkey1
3965	aesdeclast	$in0,$inout1
3966	pxor		$rndkey0,$iv
3967	movdqu		0x70($inp),$rndkey0	# next IV
3968	aesdeclast	$in1,$inout2
3969	lea		0x80($inp),$inp
3970	movdqu		0x00($inp_),$in0
3971	aesdeclast	$in2,$inout3
3972	aesdeclast	$in3,$inout4
3973	movdqu		0x10($inp_),$in1
3974	movdqu		0x20($inp_),$in2
3975	aesdeclast	$in4,$inout5
3976	aesdeclast	$rndkey1,$inout6
3977	movdqu		0x30($inp_),$in3
3978	movdqu		0x40($inp_),$in4
3979	aesdeclast	$iv,$inout7
3980	movdqa		$rndkey0,$iv		# return $iv
3981	movdqu		0x50($inp_),$rndkey1
3982	$movkey		-0x70($key),$rndkey0
3983
3984	movups		$inout0,($out)		# store output
3985	movdqa		$in0,$inout0
3986	movups		$inout1,0x10($out)
3987	movdqa		$in1,$inout1
3988	movups		$inout2,0x20($out)
3989	movdqa		$in2,$inout2
3990	movups		$inout3,0x30($out)
3991	movdqa		$in3,$inout3
3992	movups		$inout4,0x40($out)
3993	movdqa		$in4,$inout4
3994	movups		$inout5,0x50($out)
3995	movdqa		$rndkey1,$inout5
3996	movups		$inout6,0x60($out)
3997	lea		0x70($out),$out
3998
3999	sub	\$0x80,$len
4000	ja	.Lcbc_dec_loop8
4001
4002	movaps	$inout7,$inout0
4003	lea	-0x70($key),$key
4004	add	\$0x70,$len
4005	jle	.Lcbc_dec_clear_tail_collected
4006	movups	$inout7,($out)
4007	lea	0x10($out),$out
4008	cmp	\$0x50,$len
4009	jbe	.Lcbc_dec_tail
4010
4011	movaps	$in0,$inout0
4012.Lcbc_dec_six_or_seven:
4013	cmp	\$0x60,$len
4014	ja	.Lcbc_dec_seven
4015
4016	movaps	$inout5,$inout6
4017	call	_aesni_decrypt6
4018	pxor	$iv,$inout0		# ^= IV
4019	movaps	$inout6,$iv
4020	pxor	$in0,$inout1
4021	movdqu	$inout0,($out)
4022	pxor	$in1,$inout2
4023	movdqu	$inout1,0x10($out)
4024	 pxor	$inout1,$inout1		# clear register bank
4025	pxor	$in2,$inout3
4026	movdqu	$inout2,0x20($out)
4027	 pxor	$inout2,$inout2
4028	pxor	$in3,$inout4
4029	movdqu	$inout3,0x30($out)
4030	 pxor	$inout3,$inout3
4031	pxor	$in4,$inout5
4032	movdqu	$inout4,0x40($out)
4033	 pxor	$inout4,$inout4
4034	lea	0x50($out),$out
4035	movdqa	$inout5,$inout0
4036	 pxor	$inout5,$inout5
4037	jmp	.Lcbc_dec_tail_collected
4038
4039.align	16
4040.Lcbc_dec_seven:
4041	movups	0x60($inp),$inout6
4042	xorps	$inout7,$inout7
4043	call	_aesni_decrypt8
4044	movups	0x50($inp),$inout7
4045	pxor	$iv,$inout0		# ^= IV
4046	movups	0x60($inp),$iv
4047	pxor	$in0,$inout1
4048	movdqu	$inout0,($out)
4049	pxor	$in1,$inout2
4050	movdqu	$inout1,0x10($out)
4051	 pxor	$inout1,$inout1		# clear register bank
4052	pxor	$in2,$inout3
4053	movdqu	$inout2,0x20($out)
4054	 pxor	$inout2,$inout2
4055	pxor	$in3,$inout4
4056	movdqu	$inout3,0x30($out)
4057	 pxor	$inout3,$inout3
4058	pxor	$in4,$inout5
4059	movdqu	$inout4,0x40($out)
4060	 pxor	$inout4,$inout4
4061	pxor	$inout7,$inout6
4062	movdqu	$inout5,0x50($out)
4063	 pxor	$inout5,$inout5
4064	lea	0x60($out),$out
4065	movdqa	$inout6,$inout0
4066	 pxor	$inout6,$inout6
4067	 pxor	$inout7,$inout7
4068	jmp	.Lcbc_dec_tail_collected
4069
4070.align	16
4071.Lcbc_dec_loop6:
4072	movups	$inout5,($out)
4073	lea	0x10($out),$out
4074	movdqu	0x00($inp),$inout0	# load input
4075	movdqu	0x10($inp),$inout1
4076	movdqa	$inout0,$in0
4077	movdqu	0x20($inp),$inout2
4078	movdqa	$inout1,$in1
4079	movdqu	0x30($inp),$inout3
4080	movdqa	$inout2,$in2
4081	movdqu	0x40($inp),$inout4
4082	movdqa	$inout3,$in3
4083	movdqu	0x50($inp),$inout5
4084	movdqa	$inout4,$in4
4085.Lcbc_dec_loop6_enter:
4086	lea	0x60($inp),$inp
4087	movdqa	$inout5,$inout6
4088
4089	call	_aesni_decrypt6
4090
4091	pxor	$iv,$inout0		# ^= IV
4092	movdqa	$inout6,$iv
4093	pxor	$in0,$inout1
4094	movdqu	$inout0,($out)
4095	pxor	$in1,$inout2
4096	movdqu	$inout1,0x10($out)
4097	pxor	$in2,$inout3
4098	movdqu	$inout2,0x20($out)
4099	pxor	$in3,$inout4
4100	mov	$key_,$key
4101	movdqu	$inout3,0x30($out)
4102	pxor	$in4,$inout5
4103	mov	$rnds_,$rounds
4104	movdqu	$inout4,0x40($out)
4105	lea	0x50($out),$out
4106	sub	\$0x60,$len
4107	ja	.Lcbc_dec_loop6
4108
4109	movdqa	$inout5,$inout0
4110	add	\$0x50,$len
4111	jle	.Lcbc_dec_clear_tail_collected
4112	movups	$inout5,($out)
4113	lea	0x10($out),$out
4114
4115.Lcbc_dec_tail:
4116	movups	($inp),$inout0
4117	sub	\$0x10,$len
4118	jbe	.Lcbc_dec_one		# $len is 1*16 or less
4119
4120	movups	0x10($inp),$inout1
4121	movaps	$inout0,$in0
4122	sub	\$0x10,$len
4123	jbe	.Lcbc_dec_two		# $len is 2*16 or less
4124
4125	movups	0x20($inp),$inout2
4126	movaps	$inout1,$in1
4127	sub	\$0x10,$len
4128	jbe	.Lcbc_dec_three		# $len is 3*16 or less
4129
4130	movups	0x30($inp),$inout3
4131	movaps	$inout2,$in2
4132	sub	\$0x10,$len
4133	jbe	.Lcbc_dec_four		# $len is 4*16 or less
4134
4135	movups	0x40($inp),$inout4	# $len is 5*16 or less
4136	movaps	$inout3,$in3
4137	movaps	$inout4,$in4
4138	xorps	$inout5,$inout5
4139	call	_aesni_decrypt6
4140	pxor	$iv,$inout0
4141	movaps	$in4,$iv
4142	pxor	$in0,$inout1
4143	movdqu	$inout0,($out)
4144	pxor	$in1,$inout2
4145	movdqu	$inout1,0x10($out)
4146	 pxor	$inout1,$inout1		# clear register bank
4147	pxor	$in2,$inout3
4148	movdqu	$inout2,0x20($out)
4149	 pxor	$inout2,$inout2
4150	pxor	$in3,$inout4
4151	movdqu	$inout3,0x30($out)
4152	 pxor	$inout3,$inout3
4153	lea	0x40($out),$out
4154	movdqa	$inout4,$inout0
4155	 pxor	$inout4,$inout4
4156	 pxor	$inout5,$inout5
4157	sub	\$0x10,$len
4158	jmp	.Lcbc_dec_tail_collected
4159
4160.align	16
4161.Lcbc_dec_one:
4162	movaps	$inout0,$in0
4163___
4164	&aesni_generate1("dec",$key,$rounds);
4165$code.=<<___;
4166	xorps	$iv,$inout0
4167	movaps	$in0,$iv
4168	jmp	.Lcbc_dec_tail_collected
4169.align	16
4170.Lcbc_dec_two:
4171	movaps	$inout1,$in1
4172	call	_aesni_decrypt2
4173	pxor	$iv,$inout0
4174	movaps	$in1,$iv
4175	pxor	$in0,$inout1
4176	movdqu	$inout0,($out)
4177	movdqa	$inout1,$inout0
4178	 pxor	$inout1,$inout1		# clear register bank
4179	lea	0x10($out),$out
4180	jmp	.Lcbc_dec_tail_collected
4181.align	16
4182.Lcbc_dec_three:
4183	movaps	$inout2,$in2
4184	call	_aesni_decrypt3
4185	pxor	$iv,$inout0
4186	movaps	$in2,$iv
4187	pxor	$in0,$inout1
4188	movdqu	$inout0,($out)
4189	pxor	$in1,$inout2
4190	movdqu	$inout1,0x10($out)
4191	 pxor	$inout1,$inout1		# clear register bank
4192	movdqa	$inout2,$inout0
4193	 pxor	$inout2,$inout2
4194	lea	0x20($out),$out
4195	jmp	.Lcbc_dec_tail_collected
4196.align	16
4197.Lcbc_dec_four:
4198	movaps	$inout3,$in3
4199	call	_aesni_decrypt4
4200	pxor	$iv,$inout0
4201	movaps	$in3,$iv
4202	pxor	$in0,$inout1
4203	movdqu	$inout0,($out)
4204	pxor	$in1,$inout2
4205	movdqu	$inout1,0x10($out)
4206	 pxor	$inout1,$inout1		# clear register bank
4207	pxor	$in2,$inout3
4208	movdqu	$inout2,0x20($out)
4209	 pxor	$inout2,$inout2
4210	movdqa	$inout3,$inout0
4211	 pxor	$inout3,$inout3
4212	lea	0x30($out),$out
4213	jmp	.Lcbc_dec_tail_collected
4214
4215.align	16
4216.Lcbc_dec_clear_tail_collected:
4217	pxor	$inout1,$inout1		# clear register bank
4218	pxor	$inout2,$inout2
4219	pxor	$inout3,$inout3
4220___
4221$code.=<<___ if (!$win64);
4222	pxor	$inout4,$inout4		# %xmm6..9
4223	pxor	$inout5,$inout5
4224	pxor	$inout6,$inout6
4225	pxor	$inout7,$inout7
4226___
4227$code.=<<___;
4228.Lcbc_dec_tail_collected:
4229	movups	$iv,($ivp)
4230	and	\$15,$len
4231	jnz	.Lcbc_dec_tail_partial
4232	movups	$inout0,($out)
4233	pxor	$inout0,$inout0
4234	jmp	.Lcbc_dec_ret
4235.align	16
4236.Lcbc_dec_tail_partial:
4237	movaps	$inout0,(%rsp)
4238	pxor	$inout0,$inout0
4239	mov	\$16,%rcx
4240	mov	$out,%rdi
4241	sub	$len,%rcx
4242	lea	(%rsp),%rsi
4243	.long	0x9066A4F3		# rep movsb
4244	movdqa	$inout0,(%rsp)
4245
4246.Lcbc_dec_ret:
4247	xorps	$rndkey0,$rndkey0	# %xmm0
4248	pxor	$rndkey1,$rndkey1
4249___
4250$code.=<<___ if ($win64);
4251	movaps	0x10(%rsp),%xmm6
4252	movaps	%xmm0,0x10(%rsp)	# clear stack
4253	movaps	0x20(%rsp),%xmm7
4254	movaps	%xmm0,0x20(%rsp)
4255	movaps	0x30(%rsp),%xmm8
4256	movaps	%xmm0,0x30(%rsp)
4257	movaps	0x40(%rsp),%xmm9
4258	movaps	%xmm0,0x40(%rsp)
4259	movaps	0x50(%rsp),%xmm10
4260	movaps	%xmm0,0x50(%rsp)
4261	movaps	0x60(%rsp),%xmm11
4262	movaps	%xmm0,0x60(%rsp)
4263	movaps	0x70(%rsp),%xmm12
4264	movaps	%xmm0,0x70(%rsp)
4265	movaps	0x80(%rsp),%xmm13
4266	movaps	%xmm0,0x80(%rsp)
4267	movaps	0x90(%rsp),%xmm14
4268	movaps	%xmm0,0x90(%rsp)
4269	movaps	0xa0(%rsp),%xmm15
4270	movaps	%xmm0,0xa0(%rsp)
4271___
4272$code.=<<___;
4273	mov	-8(%r11),%rbp
4274.cfi_restore	%rbp
4275	lea	(%r11),%rsp
4276.cfi_def_cfa_register	%rsp
4277.Lcbc_ret:
4278	ret
4279.cfi_endproc
4280.size	${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt
4281___
4282}
4283# int ${PREFIX}_set_decrypt_key(const unsigned char *inp,
4284#				int bits, AES_KEY *key)
4285#
4286# input:	$inp	user-supplied key
4287#		$bits	$inp length in bits
4288#		$key	pointer to key schedule
4289# output:	%eax	0 denoting success, -1 or -2 - failure (see C)
4290#		*$key	key schedule
4291#
4292{ my ($inp,$bits,$key) = @_4args;
4293  $bits =~ s/%r/%e/;
4294
4295$code.=<<___;
4296.globl	${PREFIX}_set_decrypt_key
4297.type	${PREFIX}_set_decrypt_key,\@abi-omnipotent
4298.align	16
4299${PREFIX}_set_decrypt_key:
4300.cfi_startproc
4301	.byte	0x48,0x83,0xEC,0x08	# sub rsp,8
4302.cfi_adjust_cfa_offset	8
4303	call	__aesni_set_encrypt_key
4304	shl	\$4,$bits		# rounds-1 after _aesni_set_encrypt_key
4305	test	%eax,%eax
4306	jnz	.Ldec_key_ret
4307	lea	16($key,$bits),$inp	# points at the end of key schedule
4308
4309	$movkey	($key),%xmm0		# just swap
4310	$movkey	($inp),%xmm1
4311	$movkey	%xmm0,($inp)
4312	$movkey	%xmm1,($key)
4313	lea	16($key),$key
4314	lea	-16($inp),$inp
4315
4316.Ldec_key_inverse:
4317	$movkey	($key),%xmm0		# swap and inverse
4318	$movkey	($inp),%xmm1
4319	aesimc	%xmm0,%xmm0
4320	aesimc	%xmm1,%xmm1
4321	lea	16($key),$key
4322	lea	-16($inp),$inp
4323	$movkey	%xmm0,16($inp)
4324	$movkey	%xmm1,-16($key)
4325	cmp	$key,$inp
4326	ja	.Ldec_key_inverse
4327
4328	$movkey	($key),%xmm0		# inverse middle
4329	aesimc	%xmm0,%xmm0
4330	pxor	%xmm1,%xmm1
4331	$movkey	%xmm0,($inp)
4332	pxor	%xmm0,%xmm0
4333.Ldec_key_ret:
4334	add	\$8,%rsp
4335.cfi_adjust_cfa_offset	-8
4336	ret
4337.cfi_endproc
4338.LSEH_end_set_decrypt_key:
4339.size	${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key
4340___
4341
4342# This is based on submission from Intel by
4343#	Huang Ying
4344#	Vinodh Gopal
4345#	Kahraman Akdemir
4346#
4347# Aggressively optimized in respect to aeskeygenassist's critical path
4348# and is contained in %xmm0-5 to meet Win64 ABI requirement.
4349#
4350# int ${PREFIX}_set_encrypt_key(const unsigned char *inp,
4351#				int bits, AES_KEY * const key);
4352#
4353# input:	$inp	user-supplied key
4354#		$bits	$inp length in bits
4355#		$key	pointer to key schedule
4356# output:	%eax	0 denoting success, -1 or -2 - failure (see C)
4357#		$bits	rounds-1 (used in aesni_set_decrypt_key)
4358#		*$key	key schedule
4359#		$key	pointer to key schedule (used in
4360#			aesni_set_decrypt_key)
4361#
4362# Subroutine is frame-less, which means that only volatile registers
4363# are used. Note that it's declared "abi-omnipotent", which means that
4364# amount of volatile registers is smaller on Windows.
4365#
4366$code.=<<___;
4367.globl	${PREFIX}_set_encrypt_key
4368.type	${PREFIX}_set_encrypt_key,\@abi-omnipotent
4369.align	16
4370${PREFIX}_set_encrypt_key:
4371__aesni_set_encrypt_key:
4372.cfi_startproc
4373	.byte	0x48,0x83,0xEC,0x08	# sub rsp,8
4374.cfi_adjust_cfa_offset	8
4375	mov	\$-1,%rax
4376	test	$inp,$inp
4377	jz	.Lenc_key_ret
4378	test	$key,$key
4379	jz	.Lenc_key_ret
4380
4381	mov	\$`1<<28|1<<11`,%r10d	# AVX and XOP bits
4382	movups	($inp),%xmm0		# pull first 128 bits of *userKey
4383	xorps	%xmm4,%xmm4		# low dword of xmm4 is assumed 0
4384	and	OPENSSL_ia32cap_P+4(%rip),%r10d
4385	lea	16($key),%rax		# %rax is used as modifiable copy of $key
4386	cmp	\$256,$bits
4387	je	.L14rounds
4388	cmp	\$192,$bits
4389	je	.L12rounds
4390	cmp	\$128,$bits
4391	jne	.Lbad_keybits
4392
4393.L10rounds:
4394	mov	\$9,$bits			# 10 rounds for 128-bit key
4395	cmp	\$`1<<28`,%r10d			# AVX, bit no XOP
4396	je	.L10rounds_alt
4397
4398	$movkey	%xmm0,($key)			# round 0
4399	aeskeygenassist	\$0x1,%xmm0,%xmm1	# round 1
4400	call		.Lkey_expansion_128_cold
4401	aeskeygenassist	\$0x2,%xmm0,%xmm1	# round 2
4402	call		.Lkey_expansion_128
4403	aeskeygenassist	\$0x4,%xmm0,%xmm1	# round 3
4404	call		.Lkey_expansion_128
4405	aeskeygenassist	\$0x8,%xmm0,%xmm1	# round 4
4406	call		.Lkey_expansion_128
4407	aeskeygenassist	\$0x10,%xmm0,%xmm1	# round 5
4408	call		.Lkey_expansion_128
4409	aeskeygenassist	\$0x20,%xmm0,%xmm1	# round 6
4410	call		.Lkey_expansion_128
4411	aeskeygenassist	\$0x40,%xmm0,%xmm1	# round 7
4412	call		.Lkey_expansion_128
4413	aeskeygenassist	\$0x80,%xmm0,%xmm1	# round 8
4414	call		.Lkey_expansion_128
4415	aeskeygenassist	\$0x1b,%xmm0,%xmm1	# round 9
4416	call		.Lkey_expansion_128
4417	aeskeygenassist	\$0x36,%xmm0,%xmm1	# round 10
4418	call		.Lkey_expansion_128
4419	$movkey	%xmm0,(%rax)
4420	mov	$bits,80(%rax)	# 240(%rdx)
4421	xor	%eax,%eax
4422	jmp	.Lenc_key_ret
4423
4424.align	16
4425.L10rounds_alt:
4426	movdqa	.Lkey_rotate(%rip),%xmm5
4427	mov	\$8,%r10d
4428	movdqa	.Lkey_rcon1(%rip),%xmm4
4429	movdqa	%xmm0,%xmm2
4430	movdqu	%xmm0,($key)
4431	jmp	.Loop_key128
4432
4433.align	16
4434.Loop_key128:
4435	pshufb		%xmm5,%xmm0
4436	aesenclast	%xmm4,%xmm0
4437	pslld		\$1,%xmm4
4438	lea		16(%rax),%rax
4439
4440	movdqa		%xmm2,%xmm3
4441	pslldq		\$4,%xmm2
4442	pxor		%xmm2,%xmm3
4443	pslldq		\$4,%xmm2
4444	pxor		%xmm2,%xmm3
4445	pslldq		\$4,%xmm2
4446	pxor		%xmm3,%xmm2
4447
4448	pxor		%xmm2,%xmm0
4449	movdqu		%xmm0,-16(%rax)
4450	movdqa		%xmm0,%xmm2
4451
4452	dec	%r10d
4453	jnz	.Loop_key128
4454
4455	movdqa		.Lkey_rcon1b(%rip),%xmm4
4456
4457	pshufb		%xmm5,%xmm0
4458	aesenclast	%xmm4,%xmm0
4459	pslld		\$1,%xmm4
4460
4461	movdqa		%xmm2,%xmm3
4462	pslldq		\$4,%xmm2
4463	pxor		%xmm2,%xmm3
4464	pslldq		\$4,%xmm2
4465	pxor		%xmm2,%xmm3
4466	pslldq		\$4,%xmm2
4467	pxor		%xmm3,%xmm2
4468
4469	pxor		%xmm2,%xmm0
4470	movdqu		%xmm0,(%rax)
4471
4472	movdqa		%xmm0,%xmm2
4473	pshufb		%xmm5,%xmm0
4474	aesenclast	%xmm4,%xmm0
4475
4476	movdqa		%xmm2,%xmm3
4477	pslldq		\$4,%xmm2
4478	pxor		%xmm2,%xmm3
4479	pslldq		\$4,%xmm2
4480	pxor		%xmm2,%xmm3
4481	pslldq		\$4,%xmm2
4482	pxor		%xmm3,%xmm2
4483
4484	pxor		%xmm2,%xmm0
4485	movdqu		%xmm0,16(%rax)
4486
4487	mov	$bits,96(%rax)	# 240($key)
4488	xor	%eax,%eax
4489	jmp	.Lenc_key_ret
4490
4491.align	16
4492.L12rounds:
4493	movq	16($inp),%xmm2			# remaining 1/3 of *userKey
4494	mov	\$11,$bits			# 12 rounds for 192
4495	cmp	\$`1<<28`,%r10d			# AVX, but no XOP
4496	je	.L12rounds_alt
4497
4498	$movkey	%xmm0,($key)			# round 0
4499	aeskeygenassist	\$0x1,%xmm2,%xmm1	# round 1,2
4500	call		.Lkey_expansion_192a_cold
4501	aeskeygenassist	\$0x2,%xmm2,%xmm1	# round 2,3
4502	call		.Lkey_expansion_192b
4503	aeskeygenassist	\$0x4,%xmm2,%xmm1	# round 4,5
4504	call		.Lkey_expansion_192a
4505	aeskeygenassist	\$0x8,%xmm2,%xmm1	# round 5,6
4506	call		.Lkey_expansion_192b
4507	aeskeygenassist	\$0x10,%xmm2,%xmm1	# round 7,8
4508	call		.Lkey_expansion_192a
4509	aeskeygenassist	\$0x20,%xmm2,%xmm1	# round 8,9
4510	call		.Lkey_expansion_192b
4511	aeskeygenassist	\$0x40,%xmm2,%xmm1	# round 10,11
4512	call		.Lkey_expansion_192a
4513	aeskeygenassist	\$0x80,%xmm2,%xmm1	# round 11,12
4514	call		.Lkey_expansion_192b
4515	$movkey	%xmm0,(%rax)
4516	mov	$bits,48(%rax)	# 240(%rdx)
4517	xor	%rax, %rax
4518	jmp	.Lenc_key_ret
4519
4520.align	16
4521.L12rounds_alt:
4522	movdqa	.Lkey_rotate192(%rip),%xmm5
4523	movdqa	.Lkey_rcon1(%rip),%xmm4
4524	mov	\$8,%r10d
4525	movdqu	%xmm0,($key)
4526	jmp	.Loop_key192
4527
4528.align	16
4529.Loop_key192:
4530	movq		%xmm2,0(%rax)
4531	movdqa		%xmm2,%xmm1
4532	pshufb		%xmm5,%xmm2
4533	aesenclast	%xmm4,%xmm2
4534	pslld		\$1, %xmm4
4535	lea		24(%rax),%rax
4536
4537	movdqa		%xmm0,%xmm3
4538	pslldq		\$4,%xmm0
4539	pxor		%xmm0,%xmm3
4540	pslldq		\$4,%xmm0
4541	pxor		%xmm0,%xmm3
4542	pslldq		\$4,%xmm0
4543	pxor		%xmm3,%xmm0
4544
4545	pshufd		\$0xff,%xmm0,%xmm3
4546	pxor		%xmm1,%xmm3
4547	pslldq		\$4,%xmm1
4548	pxor		%xmm1,%xmm3
4549
4550	pxor		%xmm2,%xmm0
4551	pxor		%xmm3,%xmm2
4552	movdqu		%xmm0,-16(%rax)
4553
4554	dec	%r10d
4555	jnz	.Loop_key192
4556
4557	mov	$bits,32(%rax)	# 240($key)
4558	xor	%eax,%eax
4559	jmp	.Lenc_key_ret
4560
4561.align	16
4562.L14rounds:
4563	movups	16($inp),%xmm2			# remaining half of *userKey
4564	mov	\$13,$bits			# 14 rounds for 256
4565	lea	16(%rax),%rax
4566	cmp	\$`1<<28`,%r10d			# AVX, but no XOP
4567	je	.L14rounds_alt
4568
4569	$movkey	%xmm0,($key)			# round 0
4570	$movkey	%xmm2,16($key)			# round 1
4571	aeskeygenassist	\$0x1,%xmm2,%xmm1	# round 2
4572	call		.Lkey_expansion_256a_cold
4573	aeskeygenassist	\$0x1,%xmm0,%xmm1	# round 3
4574	call		.Lkey_expansion_256b
4575	aeskeygenassist	\$0x2,%xmm2,%xmm1	# round 4
4576	call		.Lkey_expansion_256a
4577	aeskeygenassist	\$0x2,%xmm0,%xmm1	# round 5
4578	call		.Lkey_expansion_256b
4579	aeskeygenassist	\$0x4,%xmm2,%xmm1	# round 6
4580	call		.Lkey_expansion_256a
4581	aeskeygenassist	\$0x4,%xmm0,%xmm1	# round 7
4582	call		.Lkey_expansion_256b
4583	aeskeygenassist	\$0x8,%xmm2,%xmm1	# round 8
4584	call		.Lkey_expansion_256a
4585	aeskeygenassist	\$0x8,%xmm0,%xmm1	# round 9
4586	call		.Lkey_expansion_256b
4587	aeskeygenassist	\$0x10,%xmm2,%xmm1	# round 10
4588	call		.Lkey_expansion_256a
4589	aeskeygenassist	\$0x10,%xmm0,%xmm1	# round 11
4590	call		.Lkey_expansion_256b
4591	aeskeygenassist	\$0x20,%xmm2,%xmm1	# round 12
4592	call		.Lkey_expansion_256a
4593	aeskeygenassist	\$0x20,%xmm0,%xmm1	# round 13
4594	call		.Lkey_expansion_256b
4595	aeskeygenassist	\$0x40,%xmm2,%xmm1	# round 14
4596	call		.Lkey_expansion_256a
4597	$movkey	%xmm0,(%rax)
4598	mov	$bits,16(%rax)	# 240(%rdx)
4599	xor	%rax,%rax
4600	jmp	.Lenc_key_ret
4601
4602.align	16
4603.L14rounds_alt:
4604	movdqa	.Lkey_rotate(%rip),%xmm5
4605	movdqa	.Lkey_rcon1(%rip),%xmm4
4606	mov	\$7,%r10d
4607	movdqu	%xmm0,0($key)
4608	movdqa	%xmm2,%xmm1
4609	movdqu	%xmm2,16($key)
4610	jmp	.Loop_key256
4611
4612.align	16
4613.Loop_key256:
4614	pshufb		%xmm5,%xmm2
4615	aesenclast	%xmm4,%xmm2
4616
4617	movdqa		%xmm0,%xmm3
4618	pslldq		\$4,%xmm0
4619	pxor		%xmm0,%xmm3
4620	pslldq		\$4,%xmm0
4621	pxor		%xmm0,%xmm3
4622	pslldq		\$4,%xmm0
4623	pxor		%xmm3,%xmm0
4624	pslld		\$1,%xmm4
4625
4626	pxor		%xmm2,%xmm0
4627	movdqu		%xmm0,(%rax)
4628
4629	dec	%r10d
4630	jz	.Ldone_key256
4631
4632	pshufd		\$0xff,%xmm0,%xmm2
4633	pxor		%xmm3,%xmm3
4634	aesenclast	%xmm3,%xmm2
4635
4636	movdqa		%xmm1,%xmm3
4637	pslldq		\$4,%xmm1
4638	pxor		%xmm1,%xmm3
4639	pslldq		\$4,%xmm1
4640	pxor		%xmm1,%xmm3
4641	pslldq		\$4,%xmm1
4642	pxor		%xmm3,%xmm1
4643
4644	pxor		%xmm1,%xmm2
4645	movdqu		%xmm2,16(%rax)
4646	lea		32(%rax),%rax
4647	movdqa		%xmm2,%xmm1
4648
4649	jmp	.Loop_key256
4650
4651.Ldone_key256:
4652	mov	$bits,16(%rax)	# 240($key)
4653	xor	%eax,%eax
4654	jmp	.Lenc_key_ret
4655
4656.align	16
4657.Lbad_keybits:
4658	mov	\$-2,%rax
4659.Lenc_key_ret:
4660	pxor	%xmm0,%xmm0
4661	pxor	%xmm1,%xmm1
4662	pxor	%xmm2,%xmm2
4663	pxor	%xmm3,%xmm3
4664	pxor	%xmm4,%xmm4
4665	pxor	%xmm5,%xmm5
4666	add	\$8,%rsp
4667.cfi_adjust_cfa_offset	-8
4668	ret
4669.LSEH_end_set_encrypt_key:
4670
4671.align	16
4672.Lkey_expansion_128:
4673	$movkey	%xmm0,(%rax)
4674	lea	16(%rax),%rax
4675.Lkey_expansion_128_cold:
4676	shufps	\$0b00010000,%xmm0,%xmm4
4677	xorps	%xmm4, %xmm0
4678	shufps	\$0b10001100,%xmm0,%xmm4
4679	xorps	%xmm4, %xmm0
4680	shufps	\$0b11111111,%xmm1,%xmm1	# critical path
4681	xorps	%xmm1,%xmm0
4682	ret
4683
4684.align 16
4685.Lkey_expansion_192a:
4686	$movkey	%xmm0,(%rax)
4687	lea	16(%rax),%rax
4688.Lkey_expansion_192a_cold:
4689	movaps	%xmm2, %xmm5
4690.Lkey_expansion_192b_warm:
4691	shufps	\$0b00010000,%xmm0,%xmm4
4692	movdqa	%xmm2,%xmm3
4693	xorps	%xmm4,%xmm0
4694	shufps	\$0b10001100,%xmm0,%xmm4
4695	pslldq	\$4,%xmm3
4696	xorps	%xmm4,%xmm0
4697	pshufd	\$0b01010101,%xmm1,%xmm1	# critical path
4698	pxor	%xmm3,%xmm2
4699	pxor	%xmm1,%xmm0
4700	pshufd	\$0b11111111,%xmm0,%xmm3
4701	pxor	%xmm3,%xmm2
4702	ret
4703
4704.align 16
4705.Lkey_expansion_192b:
4706	movaps	%xmm0,%xmm3
4707	shufps	\$0b01000100,%xmm0,%xmm5
4708	$movkey	%xmm5,(%rax)
4709	shufps	\$0b01001110,%xmm2,%xmm3
4710	$movkey	%xmm3,16(%rax)
4711	lea	32(%rax),%rax
4712	jmp	.Lkey_expansion_192b_warm
4713
4714.align	16
4715.Lkey_expansion_256a:
4716	$movkey	%xmm2,(%rax)
4717	lea	16(%rax),%rax
4718.Lkey_expansion_256a_cold:
4719	shufps	\$0b00010000,%xmm0,%xmm4
4720	xorps	%xmm4,%xmm0
4721	shufps	\$0b10001100,%xmm0,%xmm4
4722	xorps	%xmm4,%xmm0
4723	shufps	\$0b11111111,%xmm1,%xmm1	# critical path
4724	xorps	%xmm1,%xmm0
4725	ret
4726
4727.align 16
4728.Lkey_expansion_256b:
4729	$movkey	%xmm0,(%rax)
4730	lea	16(%rax),%rax
4731
4732	shufps	\$0b00010000,%xmm2,%xmm4
4733	xorps	%xmm4,%xmm2
4734	shufps	\$0b10001100,%xmm2,%xmm4
4735	xorps	%xmm4,%xmm2
4736	shufps	\$0b10101010,%xmm1,%xmm1	# critical path
4737	xorps	%xmm1,%xmm2
4738	ret
4739.cfi_endproc
4740.size	${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key
4741.size	__aesni_set_encrypt_key,.-__aesni_set_encrypt_key
4742___
4743}
4744
4745$code.=<<___;
4746.align	64
4747.Lbswap_mask:
4748	.byte	15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
4749.Lincrement32:
4750	.long	6,6,6,0
4751.Lincrement64:
4752	.long	1,0,0,0
4753.Lxts_magic:
4754	.long	0x87,0,1,0
4755.Lincrement1:
4756	.byte	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
4757.Lkey_rotate:
4758	.long	0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d
4759.Lkey_rotate192:
4760	.long	0x04070605,0x04070605,0x04070605,0x04070605
4761.Lkey_rcon1:
4762	.long	1,1,1,1
4763.Lkey_rcon1b:
4764	.long	0x1b,0x1b,0x1b,0x1b
4765
4766.asciz  "AES for Intel AES-NI, CRYPTOGAMS by <appro\@openssl.org>"
4767.align	64
4768___
4769
4770# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
4771#		CONTEXT *context,DISPATCHER_CONTEXT *disp)
4772if ($win64) {
4773$rec="%rcx";
4774$frame="%rdx";
4775$context="%r8";
4776$disp="%r9";
4777
4778$code.=<<___;
4779.extern	__imp_RtlVirtualUnwind
4780___
4781$code.=<<___ if ($PREFIX eq "aesni");
4782.type	ecb_ccm64_se_handler,\@abi-omnipotent
4783.align	16
4784ecb_ccm64_se_handler:
4785	push	%rsi
4786	push	%rdi
4787	push	%rbx
4788	push	%rbp
4789	push	%r12
4790	push	%r13
4791	push	%r14
4792	push	%r15
4793	pushfq
4794	sub	\$64,%rsp
4795
4796	mov	120($context),%rax	# pull context->Rax
4797	mov	248($context),%rbx	# pull context->Rip
4798
4799	mov	8($disp),%rsi		# disp->ImageBase
4800	mov	56($disp),%r11		# disp->HandlerData
4801
4802	mov	0(%r11),%r10d		# HandlerData[0]
4803	lea	(%rsi,%r10),%r10	# prologue label
4804	cmp	%r10,%rbx		# context->Rip<prologue label
4805	jb	.Lcommon_seh_tail
4806
4807	mov	152($context),%rax	# pull context->Rsp
4808
4809	mov	4(%r11),%r10d		# HandlerData[1]
4810	lea	(%rsi,%r10),%r10	# epilogue label
4811	cmp	%r10,%rbx		# context->Rip>=epilogue label
4812	jae	.Lcommon_seh_tail
4813
4814	lea	0(%rax),%rsi		# %xmm save area
4815	lea	512($context),%rdi	# &context.Xmm6
4816	mov	\$8,%ecx		# 4*sizeof(%xmm0)/sizeof(%rax)
4817	.long	0xa548f3fc		# cld; rep movsq
4818	lea	0x58(%rax),%rax		# adjust stack pointer
4819
4820	jmp	.Lcommon_seh_tail
4821.size	ecb_ccm64_se_handler,.-ecb_ccm64_se_handler
4822
4823.type	ctr_xts_se_handler,\@abi-omnipotent
4824.align	16
4825ctr_xts_se_handler:
4826	push	%rsi
4827	push	%rdi
4828	push	%rbx
4829	push	%rbp
4830	push	%r12
4831	push	%r13
4832	push	%r14
4833	push	%r15
4834	pushfq
4835	sub	\$64,%rsp
4836
4837	mov	120($context),%rax	# pull context->Rax
4838	mov	248($context),%rbx	# pull context->Rip
4839
4840	mov	8($disp),%rsi		# disp->ImageBase
4841	mov	56($disp),%r11		# disp->HandlerData
4842
4843	mov	0(%r11),%r10d		# HandlerData[0]
4844	lea	(%rsi,%r10),%r10	# prologue label
4845	cmp	%r10,%rbx		# context->Rip<prologue label
4846	jb	.Lcommon_seh_tail
4847
4848	mov	152($context),%rax	# pull context->Rsp
4849
4850	mov	4(%r11),%r10d		# HandlerData[1]
4851	lea	(%rsi,%r10),%r10	# epilogue label
4852	cmp	%r10,%rbx		# context->Rip>=epilogue label
4853	jae	.Lcommon_seh_tail
4854
4855	mov	208($context),%rax	# pull context->R11
4856
4857	lea	-0xa8(%rax),%rsi	# %xmm save area
4858	lea	512($context),%rdi	# & context.Xmm6
4859	mov	\$20,%ecx		# 10*sizeof(%xmm0)/sizeof(%rax)
4860	.long	0xa548f3fc		# cld; rep movsq
4861
4862	mov	-8(%rax),%rbp		# restore saved %rbp
4863	mov	%rbp,160($context)	# restore context->Rbp
4864	jmp	.Lcommon_seh_tail
4865.size	ctr_xts_se_handler,.-ctr_xts_se_handler
4866
4867.type	ocb_se_handler,\@abi-omnipotent
4868.align	16
4869ocb_se_handler:
4870	push	%rsi
4871	push	%rdi
4872	push	%rbx
4873	push	%rbp
4874	push	%r12
4875	push	%r13
4876	push	%r14
4877	push	%r15
4878	pushfq
4879	sub	\$64,%rsp
4880
4881	mov	120($context),%rax	# pull context->Rax
4882	mov	248($context),%rbx	# pull context->Rip
4883
4884	mov	8($disp),%rsi		# disp->ImageBase
4885	mov	56($disp),%r11		# disp->HandlerData
4886
4887	mov	0(%r11),%r10d		# HandlerData[0]
4888	lea	(%rsi,%r10),%r10	# prologue label
4889	cmp	%r10,%rbx		# context->Rip<prologue label
4890	jb	.Lcommon_seh_tail
4891
4892	mov	4(%r11),%r10d		# HandlerData[1]
4893	lea	(%rsi,%r10),%r10	# epilogue label
4894	cmp	%r10,%rbx		# context->Rip>=epilogue label
4895	jae	.Lcommon_seh_tail
4896
4897	mov	8(%r11),%r10d		# HandlerData[2]
4898	lea	(%rsi,%r10),%r10
4899	cmp	%r10,%rbx		# context->Rip>=pop label
4900	jae	.Locb_no_xmm
4901
4902	mov	152($context),%rax	# pull context->Rsp
4903
4904	lea	(%rax),%rsi		# %xmm save area
4905	lea	512($context),%rdi	# & context.Xmm6
4906	mov	\$20,%ecx		# 10*sizeof(%xmm0)/sizeof(%rax)
4907	.long	0xa548f3fc		# cld; rep movsq
4908	lea	0xa0+0x28(%rax),%rax
4909
4910.Locb_no_xmm:
4911	mov	-8(%rax),%rbx
4912	mov	-16(%rax),%rbp
4913	mov	-24(%rax),%r12
4914	mov	-32(%rax),%r13
4915	mov	-40(%rax),%r14
4916
4917	mov	%rbx,144($context)	# restore context->Rbx
4918	mov	%rbp,160($context)	# restore context->Rbp
4919	mov	%r12,216($context)	# restore context->R12
4920	mov	%r13,224($context)	# restore context->R13
4921	mov	%r14,232($context)	# restore context->R14
4922
4923	jmp	.Lcommon_seh_tail
4924.size	ocb_se_handler,.-ocb_se_handler
4925___
4926$code.=<<___;
4927.type	cbc_se_handler,\@abi-omnipotent
4928.align	16
4929cbc_se_handler:
4930	push	%rsi
4931	push	%rdi
4932	push	%rbx
4933	push	%rbp
4934	push	%r12
4935	push	%r13
4936	push	%r14
4937	push	%r15
4938	pushfq
4939	sub	\$64,%rsp
4940
4941	mov	152($context),%rax	# pull context->Rsp
4942	mov	248($context),%rbx	# pull context->Rip
4943
4944	lea	.Lcbc_decrypt_bulk(%rip),%r10
4945	cmp	%r10,%rbx		# context->Rip<"prologue" label
4946	jb	.Lcommon_seh_tail
4947
4948	mov	120($context),%rax	# pull context->Rax
4949
4950	lea	.Lcbc_decrypt_body(%rip),%r10
4951	cmp	%r10,%rbx		# context->Rip<cbc_decrypt_body
4952	jb	.Lcommon_seh_tail
4953
4954	mov	152($context),%rax	# pull context->Rsp
4955
4956	lea	.Lcbc_ret(%rip),%r10
4957	cmp	%r10,%rbx		# context->Rip>="epilogue" label
4958	jae	.Lcommon_seh_tail
4959
4960	lea	16(%rax),%rsi		# %xmm save area
4961	lea	512($context),%rdi	# &context.Xmm6
4962	mov	\$20,%ecx		# 10*sizeof(%xmm0)/sizeof(%rax)
4963	.long	0xa548f3fc		# cld; rep movsq
4964
4965	mov	208($context),%rax	# pull context->R11
4966
4967	mov	-8(%rax),%rbp		# restore saved %rbp
4968	mov	%rbp,160($context)	# restore context->Rbp
4969
4970.Lcommon_seh_tail:
4971	mov	8(%rax),%rdi
4972	mov	16(%rax),%rsi
4973	mov	%rax,152($context)	# restore context->Rsp
4974	mov	%rsi,168($context)	# restore context->Rsi
4975	mov	%rdi,176($context)	# restore context->Rdi
4976
4977	mov	40($disp),%rdi		# disp->ContextRecord
4978	mov	$context,%rsi		# context
4979	mov	\$154,%ecx		# sizeof(CONTEXT)
4980	.long	0xa548f3fc		# cld; rep movsq
4981
4982	mov	$disp,%rsi
4983	xor	%rcx,%rcx		# arg1, UNW_FLAG_NHANDLER
4984	mov	8(%rsi),%rdx		# arg2, disp->ImageBase
4985	mov	0(%rsi),%r8		# arg3, disp->ControlPc
4986	mov	16(%rsi),%r9		# arg4, disp->FunctionEntry
4987	mov	40(%rsi),%r10		# disp->ContextRecord
4988	lea	56(%rsi),%r11		# &disp->HandlerData
4989	lea	24(%rsi),%r12		# &disp->EstablisherFrame
4990	mov	%r10,32(%rsp)		# arg5
4991	mov	%r11,40(%rsp)		# arg6
4992	mov	%r12,48(%rsp)		# arg7
4993	mov	%rcx,56(%rsp)		# arg8, (NULL)
4994	call	*__imp_RtlVirtualUnwind(%rip)
4995
4996	mov	\$1,%eax		# ExceptionContinueSearch
4997	add	\$64,%rsp
4998	popfq
4999	pop	%r15
5000	pop	%r14
5001	pop	%r13
5002	pop	%r12
5003	pop	%rbp
5004	pop	%rbx
5005	pop	%rdi
5006	pop	%rsi
5007	ret
5008.size	cbc_se_handler,.-cbc_se_handler
5009
5010.section	.pdata
5011.align	4
5012___
5013$code.=<<___ if ($PREFIX eq "aesni");
5014	.rva	.LSEH_begin_aesni_ecb_encrypt
5015	.rva	.LSEH_end_aesni_ecb_encrypt
5016	.rva	.LSEH_info_ecb
5017
5018	.rva	.LSEH_begin_aesni_ccm64_encrypt_blocks
5019	.rva	.LSEH_end_aesni_ccm64_encrypt_blocks
5020	.rva	.LSEH_info_ccm64_enc
5021
5022	.rva	.LSEH_begin_aesni_ccm64_decrypt_blocks
5023	.rva	.LSEH_end_aesni_ccm64_decrypt_blocks
5024	.rva	.LSEH_info_ccm64_dec
5025
5026	.rva	.LSEH_begin_aesni_ctr32_encrypt_blocks
5027	.rva	.LSEH_end_aesni_ctr32_encrypt_blocks
5028	.rva	.LSEH_info_ctr32
5029
5030	.rva	.LSEH_begin_aesni_xts_encrypt
5031	.rva	.LSEH_end_aesni_xts_encrypt
5032	.rva	.LSEH_info_xts_enc
5033
5034	.rva	.LSEH_begin_aesni_xts_decrypt
5035	.rva	.LSEH_end_aesni_xts_decrypt
5036	.rva	.LSEH_info_xts_dec
5037
5038	.rva	.LSEH_begin_aesni_ocb_encrypt
5039	.rva	.LSEH_end_aesni_ocb_encrypt
5040	.rva	.LSEH_info_ocb_enc
5041
5042	.rva	.LSEH_begin_aesni_ocb_decrypt
5043	.rva	.LSEH_end_aesni_ocb_decrypt
5044	.rva	.LSEH_info_ocb_dec
5045___
5046$code.=<<___;
5047	.rva	.LSEH_begin_${PREFIX}_cbc_encrypt
5048	.rva	.LSEH_end_${PREFIX}_cbc_encrypt
5049	.rva	.LSEH_info_cbc
5050
5051	.rva	${PREFIX}_set_decrypt_key
5052	.rva	.LSEH_end_set_decrypt_key
5053	.rva	.LSEH_info_key
5054
5055	.rva	${PREFIX}_set_encrypt_key
5056	.rva	.LSEH_end_set_encrypt_key
5057	.rva	.LSEH_info_key
5058.section	.xdata
5059.align	8
5060___
5061$code.=<<___ if ($PREFIX eq "aesni");
5062.LSEH_info_ecb:
5063	.byte	9,0,0,0
5064	.rva	ecb_ccm64_se_handler
5065	.rva	.Lecb_enc_body,.Lecb_enc_ret		# HandlerData[]
5066.LSEH_info_ccm64_enc:
5067	.byte	9,0,0,0
5068	.rva	ecb_ccm64_se_handler
5069	.rva	.Lccm64_enc_body,.Lccm64_enc_ret	# HandlerData[]
5070.LSEH_info_ccm64_dec:
5071	.byte	9,0,0,0
5072	.rva	ecb_ccm64_se_handler
5073	.rva	.Lccm64_dec_body,.Lccm64_dec_ret	# HandlerData[]
5074.LSEH_info_ctr32:
5075	.byte	9,0,0,0
5076	.rva	ctr_xts_se_handler
5077	.rva	.Lctr32_body,.Lctr32_epilogue		# HandlerData[]
5078.LSEH_info_xts_enc:
5079	.byte	9,0,0,0
5080	.rva	ctr_xts_se_handler
5081	.rva	.Lxts_enc_body,.Lxts_enc_epilogue	# HandlerData[]
5082.LSEH_info_xts_dec:
5083	.byte	9,0,0,0
5084	.rva	ctr_xts_se_handler
5085	.rva	.Lxts_dec_body,.Lxts_dec_epilogue	# HandlerData[]
5086.LSEH_info_ocb_enc:
5087	.byte	9,0,0,0
5088	.rva	ocb_se_handler
5089	.rva	.Locb_enc_body,.Locb_enc_epilogue	# HandlerData[]
5090	.rva	.Locb_enc_pop
5091	.long	0
5092.LSEH_info_ocb_dec:
5093	.byte	9,0,0,0
5094	.rva	ocb_se_handler
5095	.rva	.Locb_dec_body,.Locb_dec_epilogue	# HandlerData[]
5096	.rva	.Locb_dec_pop
5097	.long	0
5098___
5099$code.=<<___;
5100.LSEH_info_cbc:
5101	.byte	9,0,0,0
5102	.rva	cbc_se_handler
5103.LSEH_info_key:
5104	.byte	0x01,0x04,0x01,0x00
5105	.byte	0x04,0x02,0x00,0x00	# sub rsp,8
5106___
5107}
5108
5109sub rex {
5110  local *opcode=shift;
5111  my ($dst,$src)=@_;
5112  my $rex=0;
5113
5114    $rex|=0x04			if($dst>=8);
5115    $rex|=0x01			if($src>=8);
5116    push @opcode,$rex|0x40	if($rex);
5117}
5118
5119sub aesni {
5120  my $line=shift;
5121  my @opcode=(0x66);
5122
5123    if ($line=~/(aeskeygenassist)\s+\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
5124	rex(\@opcode,$4,$3);
5125	push @opcode,0x0f,0x3a,0xdf;
5126	push @opcode,0xc0|($3&7)|(($4&7)<<3);	# ModR/M
5127	my $c=$2;
5128	push @opcode,$c=~/^0/?oct($c):$c;
5129	return ".byte\t".join(',',@opcode);
5130    }
5131    elsif ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) {
5132	my %opcodelet = (
5133		"aesimc" => 0xdb,
5134		"aesenc" => 0xdc,	"aesenclast" => 0xdd,
5135		"aesdec" => 0xde,	"aesdeclast" => 0xdf
5136	);
5137	return undef if (!defined($opcodelet{$1}));
5138	rex(\@opcode,$3,$2);
5139	push @opcode,0x0f,0x38,$opcodelet{$1};
5140	push @opcode,0xc0|($2&7)|(($3&7)<<3);	# ModR/M
5141	return ".byte\t".join(',',@opcode);
5142    }
5143    elsif ($line=~/(aes[a-z]+)\s+([0x1-9a-fA-F]*)\(%rsp\),\s*%xmm([0-9]+)/) {
5144	my %opcodelet = (
5145		"aesenc" => 0xdc,	"aesenclast" => 0xdd,
5146		"aesdec" => 0xde,	"aesdeclast" => 0xdf
5147	);
5148	return undef if (!defined($opcodelet{$1}));
5149	my $off = $2;
5150	push @opcode,0x44 if ($3>=8);
5151	push @opcode,0x0f,0x38,$opcodelet{$1};
5152	push @opcode,0x44|(($3&7)<<3),0x24;	# ModR/M
5153	push @opcode,($off=~/^0/?oct($off):$off)&0xff;
5154	return ".byte\t".join(',',@opcode);
5155    }
5156    return $line;
5157}
5158
5159sub movbe {
5160	".byte	0x0f,0x38,0xf1,0x44,0x24,".shift;
5161}
5162
5163$code =~ s/\`([^\`]*)\`/eval($1)/gem;
5164$code =~ s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/gem;
5165#$code =~ s/\bmovbe\s+%eax/bswap %eax; mov %eax/gm;	# debugging artefact
5166$code =~ s/\bmovbe\s+%eax,\s*([0-9]+)\(%rsp\)/movbe($1)/gem;
5167
5168print $code;
5169
5170close STDOUT or die "error closing STDOUT: $!";
5171