Blame crypto/aes/asm/aesni-mb-x86_64.pl

Packit c4476c
#! /usr/bin/env perl
Packit c4476c
# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved.
Packit c4476c
#
Packit c4476c
# Licensed under the OpenSSL license (the "License").  You may not use
Packit c4476c
# this file except in compliance with the License.  You can obtain a copy
Packit c4476c
# in the file LICENSE in the source distribution or at
Packit c4476c
# https://www.openssl.org/source/license.html
Packit c4476c
Packit c4476c
Packit c4476c
# ====================================================================
Packit c4476c
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
Packit c4476c
# project. The module is, however, dual licensed under OpenSSL and
Packit c4476c
# CRYPTOGAMS licenses depending on where you obtain it. For further
Packit c4476c
# details see http://www.openssl.org/~appro/cryptogams/.
Packit c4476c
# ====================================================================
Packit c4476c
Packit c4476c
# Multi-buffer AES-NI procedures process several independent buffers
Packit c4476c
# in parallel by interleaving independent instructions.
Packit c4476c
#
Packit c4476c
# Cycles per byte for interleave factor 4:
Packit c4476c
#
Packit c4476c
#			asymptotic	measured
Packit c4476c
#			---------------------------
Packit c4476c
# Westmere		5.00/4=1.25	5.13/4=1.28
Packit c4476c
# Atom			15.0/4=3.75	?15.7/4=3.93
Packit c4476c
# Sandy Bridge		5.06/4=1.27	5.18/4=1.29
Packit c4476c
# Ivy Bridge		5.06/4=1.27	5.14/4=1.29
Packit c4476c
# Haswell		4.44/4=1.11	4.44/4=1.11
Packit c4476c
# Bulldozer		5.75/4=1.44	5.76/4=1.44
Packit c4476c
#
Packit c4476c
# Cycles per byte for interleave factor 8 (not implemented for
Packit c4476c
# pre-AVX processors, where higher interleave factor incidentally
Packit c4476c
# doesn't result in improvement):
Packit c4476c
#
Packit c4476c
#			asymptotic	measured
Packit c4476c
#			---------------------------
Packit c4476c
# Sandy Bridge		5.06/8=0.64	7.10/8=0.89(*)
Packit c4476c
# Ivy Bridge		5.06/8=0.64	7.14/8=0.89(*)
Packit c4476c
# Haswell		5.00/8=0.63	5.00/8=0.63
Packit c4476c
# Bulldozer		5.75/8=0.72	5.77/8=0.72
Packit c4476c
#
Packit c4476c
# (*)	Sandy/Ivy Bridge are known to handle high interleave factors
Packit c4476c
#	suboptimally;
Packit c4476c
Packit c4476c
$flavour = shift;
Packit c4476c
$output  = shift;
Packit c4476c
if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
Packit c4476c
Packit c4476c
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
Packit c4476c
Packit c4476c
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
Packit c4476c
( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
Packit c4476c
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
Packit c4476c
die "can't locate x86_64-xlate.pl";
Packit c4476c
Packit c4476c
$avx=0;
Packit c4476c
Packit c4476c
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
Packit c4476c
		=~ /GNU assembler version ([2-9]\.[0-9]+)/) {
Packit c4476c
	$avx = ($1>=2.19) + ($1>=2.22);
Packit c4476c
}
Packit c4476c
Packit c4476c
if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
Packit c4476c
	   `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
Packit c4476c
	$avx = ($1>=2.09) + ($1>=2.10);
Packit c4476c
}
Packit c4476c
Packit c4476c
if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
Packit c4476c
	   `ml64 2>&1` =~ /Version ([0-9]+)\./) {
Packit c4476c
	$avx = ($1>=10) + ($1>=11);
Packit c4476c
}
Packit c4476c
Packit c4476c
if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([0-9]+\.[0-9]+)/) {
Packit c4476c
	$avx = ($2>=3.0) + ($2>3.0);
Packit c4476c
}
Packit c4476c
Packit c4476c
open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
Packit c4476c
*STDOUT=*OUT;
Packit c4476c
Packit c4476c
# void aesni_multi_cbc_encrypt (
Packit c4476c
#     struct {	void *inp,*out; int blocks; double iv[2]; } inp[8];
Packit c4476c
#     const AES_KEY *key,
Packit c4476c
#     int num);		/* 1 or 2 */
Packit c4476c
#
Packit c4476c
$inp="%rdi";	# 1st arg
Packit c4476c
$key="%rsi";	# 2nd arg
Packit c4476c
$num="%edx";
Packit c4476c
Packit c4476c
@inptr=map("%r$_",(8..11));
Packit c4476c
@outptr=map("%r$_",(12..15));
Packit c4476c
Packit c4476c
($rndkey0,$rndkey1)=("%xmm0","%xmm1");
Packit c4476c
@out=map("%xmm$_",(2..5));
Packit c4476c
@inp=map("%xmm$_",(6..9));
Packit c4476c
($counters,$mask,$zero)=map("%xmm$_",(10..12));
Packit c4476c
Packit c4476c
($rounds,$one,$sink,$offset)=("%eax","%ecx","%rbp","%rbx");
Packit c4476c
Packit c4476c
$code.=<<___;
Packit c4476c
.text
Packit c4476c
Packit c4476c
.extern	OPENSSL_ia32cap_P
Packit c4476c
Packit c4476c
.globl	aesni_multi_cbc_encrypt
Packit c4476c
.type	aesni_multi_cbc_encrypt,\@function,3
Packit c4476c
.align	32
Packit c4476c
aesni_multi_cbc_encrypt:
Packit c4476c
.cfi_startproc
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($avx);
Packit c4476c
	cmp	\$2,$num
Packit c4476c
	jb	.Lenc_non_avx
Packit c4476c
	mov	OPENSSL_ia32cap_P+4(%rip),%ecx
Packit c4476c
	test	\$`1<<28`,%ecx			# AVX bit
Packit c4476c
	jnz	_avx_cbc_enc_shortcut
Packit c4476c
	jmp	.Lenc_non_avx
Packit c4476c
.align	16
Packit c4476c
.Lenc_non_avx:
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	mov	%rsp,%rax
Packit c4476c
.cfi_def_cfa_register	%rax
Packit c4476c
	push	%rbx
Packit c4476c
.cfi_push	%rbx
Packit c4476c
	push	%rbp
Packit c4476c
.cfi_push	%rbp
Packit c4476c
	push	%r12
Packit c4476c
.cfi_push	%r12
Packit c4476c
	push	%r13
Packit c4476c
.cfi_push	%r13
Packit c4476c
	push	%r14
Packit c4476c
.cfi_push	%r14
Packit c4476c
	push	%r15
Packit c4476c
.cfi_push	%r15
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($win64);
Packit c4476c
	lea	-0xa8(%rsp),%rsp
Packit c4476c
	movaps	%xmm6,(%rsp)
Packit c4476c
	movaps	%xmm7,0x10(%rsp)
Packit c4476c
	movaps	%xmm8,0x20(%rsp)
Packit c4476c
	movaps	%xmm9,0x30(%rsp)
Packit c4476c
	movaps	%xmm10,0x40(%rsp)
Packit c4476c
	movaps	%xmm11,0x50(%rsp)
Packit c4476c
	movaps	%xmm12,0x60(%rsp)
Packit c4476c
	movaps	%xmm13,-0x68(%rax)	# not used, saved to share se_handler
Packit c4476c
	movaps	%xmm14,-0x58(%rax)
Packit c4476c
	movaps	%xmm15,-0x48(%rax)
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	# stack layout
Packit c4476c
	#
Packit c4476c
	# +0	output sink
Packit c4476c
	# +16	input sink [original %rsp and $num]
Packit c4476c
	# +32	counters
Packit c4476c
Packit c4476c
	sub	\$48,%rsp
Packit c4476c
	and	\$-64,%rsp
Packit c4476c
	mov	%rax,16(%rsp)			# original %rsp
Packit c4476c
.cfi_cfa_expression	%rsp+16,deref,+8
Packit c4476c
Packit c4476c
.Lenc4x_body:
Packit c4476c
	movdqu	($key),$zero			# 0-round key
Packit c4476c
	lea	0x78($key),$key			# size optimization
Packit c4476c
	lea	40*2($inp),$inp
Packit c4476c
Packit c4476c
.Lenc4x_loop_grande:
Packit c4476c
	mov	$num,24(%rsp)			# original $num
Packit c4476c
	xor	$num,$num
Packit c4476c
___
Packit c4476c
for($i=0;$i<4;$i++) {
Packit c4476c
    $code.=<<___;
Packit c4476c
	mov	`40*$i+16-40*2`($inp),$one	# borrow $one for number of blocks
Packit c4476c
	mov	`40*$i+0-40*2`($inp),@inptr[$i]
Packit c4476c
	cmp	$num,$one
Packit c4476c
	mov	`40*$i+8-40*2`($inp),@outptr[$i]
Packit c4476c
	cmovg	$one,$num			# find maximum
Packit c4476c
	test	$one,$one
Packit c4476c
	movdqu	`40*$i+24-40*2`($inp),@out[$i]	# load IV
Packit c4476c
	mov	$one,`32+4*$i`(%rsp)		# initialize counters
Packit c4476c
	cmovle	%rsp,@inptr[$i]			# cancel input
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	test	$num,$num
Packit c4476c
	jz	.Lenc4x_done
Packit c4476c
Packit c4476c
	movups	0x10-0x78($key),$rndkey1
Packit c4476c
	 pxor	$zero,@out[0]
Packit c4476c
	movups	0x20-0x78($key),$rndkey0
Packit c4476c
	 pxor	$zero,@out[1]
Packit c4476c
	mov	0xf0-0x78($key),$rounds
Packit c4476c
	 pxor	$zero,@out[2]
Packit c4476c
	movdqu	(@inptr[0]),@inp[0]		# load inputs
Packit c4476c
	 pxor	$zero,@out[3]
Packit c4476c
	movdqu	(@inptr[1]),@inp[1]
Packit c4476c
	 pxor	@inp[0],@out[0]
Packit c4476c
	movdqu	(@inptr[2]),@inp[2]
Packit c4476c
	 pxor	@inp[1],@out[1]
Packit c4476c
	movdqu	(@inptr[3]),@inp[3]
Packit c4476c
	 pxor	@inp[2],@out[2]
Packit c4476c
	 pxor	@inp[3],@out[3]
Packit c4476c
	movdqa	32(%rsp),$counters		# load counters
Packit c4476c
	xor	$offset,$offset
Packit c4476c
	jmp	.Loop_enc4x
Packit c4476c
Packit c4476c
.align	32
Packit c4476c
.Loop_enc4x:
Packit c4476c
	add	\$16,$offset
Packit c4476c
	lea	16(%rsp),$sink			# sink pointer
Packit c4476c
	mov	\$1,$one			# constant of 1
Packit c4476c
	sub	$offset,$sink
Packit c4476c
Packit c4476c
	aesenc		$rndkey1,@out[0]
Packit c4476c
	prefetcht0	31(@inptr[0],$offset)	# prefetch input
Packit c4476c
	prefetcht0	31(@inptr[1],$offset)
Packit c4476c
	aesenc		$rndkey1,@out[1]
Packit c4476c
	prefetcht0	31(@inptr[2],$offset)
Packit c4476c
	prefetcht0	31(@inptr[2],$offset)
Packit c4476c
	aesenc		$rndkey1,@out[2]
Packit c4476c
	aesenc		$rndkey1,@out[3]
Packit c4476c
	movups		0x30-0x78($key),$rndkey1
Packit c4476c
___
Packit c4476c
for($i=0;$i<4;$i++) {
Packit c4476c
my $rndkey = ($i&1) ? $rndkey1 : $rndkey0;
Packit c4476c
$code.=<<___;
Packit c4476c
	 cmp		`32+4*$i`(%rsp),$one
Packit c4476c
	aesenc		$rndkey,@out[0]
Packit c4476c
	aesenc		$rndkey,@out[1]
Packit c4476c
	aesenc		$rndkey,@out[2]
Packit c4476c
	 cmovge		$sink,@inptr[$i]	# cancel input
Packit c4476c
	 cmovg		$sink,@outptr[$i]	# sink output
Packit c4476c
	aesenc		$rndkey,@out[3]
Packit c4476c
	movups		`0x40+16*$i-0x78`($key),$rndkey
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	 movdqa		$counters,$mask
Packit c4476c
	aesenc		$rndkey0,@out[0]
Packit c4476c
	prefetcht0	15(@outptr[0],$offset)	# prefetch output
Packit c4476c
	prefetcht0	15(@outptr[1],$offset)
Packit c4476c
	aesenc		$rndkey0,@out[1]
Packit c4476c
	prefetcht0	15(@outptr[2],$offset)
Packit c4476c
	prefetcht0	15(@outptr[3],$offset)
Packit c4476c
	aesenc		$rndkey0,@out[2]
Packit c4476c
	aesenc		$rndkey0,@out[3]
Packit c4476c
	movups		0x80-0x78($key),$rndkey0
Packit c4476c
	 pxor		$zero,$zero
Packit c4476c
Packit c4476c
	aesenc		$rndkey1,@out[0]
Packit c4476c
	 pcmpgtd	$zero,$mask
Packit c4476c
	 movdqu		-0x78($key),$zero	# reload 0-round key
Packit c4476c
	aesenc		$rndkey1,@out[1]
Packit c4476c
	 paddd		$mask,$counters		# decrement counters
Packit c4476c
	 movdqa		$counters,32(%rsp)	# update counters
Packit c4476c
	aesenc		$rndkey1,@out[2]
Packit c4476c
	aesenc		$rndkey1,@out[3]
Packit c4476c
	movups		0x90-0x78($key),$rndkey1
Packit c4476c
Packit c4476c
	cmp	\$11,$rounds
Packit c4476c
Packit c4476c
	aesenc		$rndkey0,@out[0]
Packit c4476c
	aesenc		$rndkey0,@out[1]
Packit c4476c
	aesenc		$rndkey0,@out[2]
Packit c4476c
	aesenc		$rndkey0,@out[3]
Packit c4476c
	movups		0xa0-0x78($key),$rndkey0
Packit c4476c
Packit c4476c
	jb	.Lenc4x_tail
Packit c4476c
Packit c4476c
	aesenc		$rndkey1,@out[0]
Packit c4476c
	aesenc		$rndkey1,@out[1]
Packit c4476c
	aesenc		$rndkey1,@out[2]
Packit c4476c
	aesenc		$rndkey1,@out[3]
Packit c4476c
	movups		0xb0-0x78($key),$rndkey1
Packit c4476c
Packit c4476c
	aesenc		$rndkey0,@out[0]
Packit c4476c
	aesenc		$rndkey0,@out[1]
Packit c4476c
	aesenc		$rndkey0,@out[2]
Packit c4476c
	aesenc		$rndkey0,@out[3]
Packit c4476c
	movups		0xc0-0x78($key),$rndkey0
Packit c4476c
Packit c4476c
	je	.Lenc4x_tail
Packit c4476c
Packit c4476c
	aesenc		$rndkey1,@out[0]
Packit c4476c
	aesenc		$rndkey1,@out[1]
Packit c4476c
	aesenc		$rndkey1,@out[2]
Packit c4476c
	aesenc		$rndkey1,@out[3]
Packit c4476c
	movups		0xd0-0x78($key),$rndkey1
Packit c4476c
Packit c4476c
	aesenc		$rndkey0,@out[0]
Packit c4476c
	aesenc		$rndkey0,@out[1]
Packit c4476c
	aesenc		$rndkey0,@out[2]
Packit c4476c
	aesenc		$rndkey0,@out[3]
Packit c4476c
	movups		0xe0-0x78($key),$rndkey0
Packit c4476c
	jmp	.Lenc4x_tail
Packit c4476c
Packit c4476c
.align	32
Packit c4476c
.Lenc4x_tail:
Packit c4476c
	aesenc		$rndkey1,@out[0]
Packit c4476c
	aesenc		$rndkey1,@out[1]
Packit c4476c
	aesenc		$rndkey1,@out[2]
Packit c4476c
	aesenc		$rndkey1,@out[3]
Packit c4476c
	 movdqu		(@inptr[0],$offset),@inp[0]
Packit c4476c
	movdqu		0x10-0x78($key),$rndkey1
Packit c4476c
Packit c4476c
	aesenclast	$rndkey0,@out[0]
Packit c4476c
	 movdqu		(@inptr[1],$offset),@inp[1]
Packit c4476c
	 pxor		$zero,@inp[0]
Packit c4476c
	aesenclast	$rndkey0,@out[1]
Packit c4476c
	 movdqu		(@inptr[2],$offset),@inp[2]
Packit c4476c
	 pxor		$zero,@inp[1]
Packit c4476c
	aesenclast	$rndkey0,@out[2]
Packit c4476c
	 movdqu		(@inptr[3],$offset),@inp[3]
Packit c4476c
	 pxor		$zero,@inp[2]
Packit c4476c
	aesenclast	$rndkey0,@out[3]
Packit c4476c
	movdqu		0x20-0x78($key),$rndkey0
Packit c4476c
	 pxor		$zero,@inp[3]
Packit c4476c
Packit c4476c
	movups		@out[0],-16(@outptr[0],$offset)
Packit c4476c
	 pxor		@inp[0],@out[0]
Packit c4476c
	movups		@out[1],-16(@outptr[1],$offset)
Packit c4476c
	 pxor		@inp[1],@out[1]
Packit c4476c
	movups		@out[2],-16(@outptr[2],$offset)
Packit c4476c
	 pxor		@inp[2],@out[2]
Packit c4476c
	movups		@out[3],-16(@outptr[3],$offset)
Packit c4476c
	 pxor		@inp[3],@out[3]
Packit c4476c
Packit c4476c
	dec	$num
Packit c4476c
	jnz	.Loop_enc4x
Packit c4476c
Packit c4476c
	mov	16(%rsp),%rax			# original %rsp
Packit c4476c
.cfi_def_cfa	%rax,8
Packit c4476c
	mov	24(%rsp),$num
Packit c4476c
Packit c4476c
	#pxor	@inp[0],@out[0]
Packit c4476c
	#pxor	@inp[1],@out[1]
Packit c4476c
	#movdqu	@out[0],`40*0+24-40*2`($inp)	# output iv FIX ME!
Packit c4476c
	#pxor	@inp[2],@out[2]
Packit c4476c
	#movdqu	@out[1],`40*1+24-40*2`($inp)
Packit c4476c
	#pxor	@inp[3],@out[3]
Packit c4476c
	#movdqu	@out[2],`40*2+24-40*2`($inp)	# won't fix, let caller
Packit c4476c
	#movdqu	@out[3],`40*3+24-40*2`($inp)	# figure this out...
Packit c4476c
Packit c4476c
	lea	`40*4`($inp),$inp
Packit c4476c
	dec	$num
Packit c4476c
	jnz	.Lenc4x_loop_grande
Packit c4476c
Packit c4476c
.Lenc4x_done:
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($win64);
Packit c4476c
	movaps	-0xd8(%rax),%xmm6
Packit c4476c
	movaps	-0xc8(%rax),%xmm7
Packit c4476c
	movaps	-0xb8(%rax),%xmm8
Packit c4476c
	movaps	-0xa8(%rax),%xmm9
Packit c4476c
	movaps	-0x98(%rax),%xmm10
Packit c4476c
	movaps	-0x88(%rax),%xmm11
Packit c4476c
	movaps	-0x78(%rax),%xmm12
Packit c4476c
	#movaps	-0x68(%rax),%xmm13
Packit c4476c
	#movaps	-0x58(%rax),%xmm14
Packit c4476c
	#movaps	-0x48(%rax),%xmm15
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	mov	-48(%rax),%r15
Packit c4476c
.cfi_restore	%r15
Packit c4476c
	mov	-40(%rax),%r14
Packit c4476c
.cfi_restore	%r14
Packit c4476c
	mov	-32(%rax),%r13
Packit c4476c
.cfi_restore	%r13
Packit c4476c
	mov	-24(%rax),%r12
Packit c4476c
.cfi_restore	%r12
Packit c4476c
	mov	-16(%rax),%rbp
Packit c4476c
.cfi_restore	%rbp
Packit c4476c
	mov	-8(%rax),%rbx
Packit c4476c
.cfi_restore	%rbx
Packit c4476c
	lea	(%rax),%rsp
Packit c4476c
.cfi_def_cfa_register	%rsp
Packit c4476c
.Lenc4x_epilogue:
Packit c4476c
	ret
Packit c4476c
.cfi_endproc
Packit c4476c
.size	aesni_multi_cbc_encrypt,.-aesni_multi_cbc_encrypt
Packit c4476c
Packit c4476c
.globl	aesni_multi_cbc_decrypt
Packit c4476c
.type	aesni_multi_cbc_decrypt,\@function,3
Packit c4476c
.align	32
Packit c4476c
aesni_multi_cbc_decrypt:
Packit c4476c
.cfi_startproc
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($avx);
Packit c4476c
	cmp	\$2,$num
Packit c4476c
	jb	.Ldec_non_avx
Packit c4476c
	mov	OPENSSL_ia32cap_P+4(%rip),%ecx
Packit c4476c
	test	\$`1<<28`,%ecx			# AVX bit
Packit c4476c
	jnz	_avx_cbc_dec_shortcut
Packit c4476c
	jmp	.Ldec_non_avx
Packit c4476c
.align	16
Packit c4476c
.Ldec_non_avx:
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	mov	%rsp,%rax
Packit c4476c
.cfi_def_cfa_register	%rax
Packit c4476c
	push	%rbx
Packit c4476c
.cfi_push	%rbx
Packit c4476c
	push	%rbp
Packit c4476c
.cfi_push	%rbp
Packit c4476c
	push	%r12
Packit c4476c
.cfi_push	%r12
Packit c4476c
	push	%r13
Packit c4476c
.cfi_push	%r13
Packit c4476c
	push	%r14
Packit c4476c
.cfi_push	%r14
Packit c4476c
	push	%r15
Packit c4476c
.cfi_push	%r15
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($win64);
Packit c4476c
	lea	-0xa8(%rsp),%rsp
Packit c4476c
	movaps	%xmm6,(%rsp)
Packit c4476c
	movaps	%xmm7,0x10(%rsp)
Packit c4476c
	movaps	%xmm8,0x20(%rsp)
Packit c4476c
	movaps	%xmm9,0x30(%rsp)
Packit c4476c
	movaps	%xmm10,0x40(%rsp)
Packit c4476c
	movaps	%xmm11,0x50(%rsp)
Packit c4476c
	movaps	%xmm12,0x60(%rsp)
Packit c4476c
	movaps	%xmm13,-0x68(%rax)	# not used, saved to share se_handler
Packit c4476c
	movaps	%xmm14,-0x58(%rax)
Packit c4476c
	movaps	%xmm15,-0x48(%rax)
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	# stack layout
Packit c4476c
	#
Packit c4476c
	# +0	output sink
Packit c4476c
	# +16	input sink [original %rsp and $num]
Packit c4476c
	# +32	counters
Packit c4476c
Packit c4476c
	sub	\$48,%rsp
Packit c4476c
	and	\$-64,%rsp
Packit c4476c
	mov	%rax,16(%rsp)			# original %rsp
Packit c4476c
.cfi_cfa_expression	%rsp+16,deref,+8
Packit c4476c
Packit c4476c
.Ldec4x_body:
Packit c4476c
	movdqu	($key),$zero			# 0-round key
Packit c4476c
	lea	0x78($key),$key			# size optimization
Packit c4476c
	lea	40*2($inp),$inp
Packit c4476c
Packit c4476c
.Ldec4x_loop_grande:
Packit c4476c
	mov	$num,24(%rsp)			# original $num
Packit c4476c
	xor	$num,$num
Packit c4476c
___
Packit c4476c
for($i=0;$i<4;$i++) {
Packit c4476c
    $code.=<<___;
Packit c4476c
	mov	`40*$i+16-40*2`($inp),$one	# borrow $one for number of blocks
Packit c4476c
	mov	`40*$i+0-40*2`($inp),@inptr[$i]
Packit c4476c
	cmp	$num,$one
Packit c4476c
	mov	`40*$i+8-40*2`($inp),@outptr[$i]
Packit c4476c
	cmovg	$one,$num			# find maximum
Packit c4476c
	test	$one,$one
Packit c4476c
	movdqu	`40*$i+24-40*2`($inp),@inp[$i]	# load IV
Packit c4476c
	mov	$one,`32+4*$i`(%rsp)		# initialize counters
Packit c4476c
	cmovle	%rsp,@inptr[$i]			# cancel input
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	test	$num,$num
Packit c4476c
	jz	.Ldec4x_done
Packit c4476c
Packit c4476c
	movups	0x10-0x78($key),$rndkey1
Packit c4476c
	movups	0x20-0x78($key),$rndkey0
Packit c4476c
	mov	0xf0-0x78($key),$rounds
Packit c4476c
	movdqu	(@inptr[0]),@out[0]		# load inputs
Packit c4476c
	movdqu	(@inptr[1]),@out[1]
Packit c4476c
	 pxor	$zero,@out[0]
Packit c4476c
	movdqu	(@inptr[2]),@out[2]
Packit c4476c
	 pxor	$zero,@out[1]
Packit c4476c
	movdqu	(@inptr[3]),@out[3]
Packit c4476c
	 pxor	$zero,@out[2]
Packit c4476c
	 pxor	$zero,@out[3]
Packit c4476c
	movdqa	32(%rsp),$counters		# load counters
Packit c4476c
	xor	$offset,$offset
Packit c4476c
	jmp	.Loop_dec4x
Packit c4476c
Packit c4476c
.align	32
Packit c4476c
.Loop_dec4x:
Packit c4476c
	add	\$16,$offset
Packit c4476c
	lea	16(%rsp),$sink			# sink pointer
Packit c4476c
	mov	\$1,$one			# constant of 1
Packit c4476c
	sub	$offset,$sink
Packit c4476c
Packit c4476c
	aesdec		$rndkey1,@out[0]
Packit c4476c
	prefetcht0	31(@inptr[0],$offset)	# prefetch input
Packit c4476c
	prefetcht0	31(@inptr[1],$offset)
Packit c4476c
	aesdec		$rndkey1,@out[1]
Packit c4476c
	prefetcht0	31(@inptr[2],$offset)
Packit c4476c
	prefetcht0	31(@inptr[3],$offset)
Packit c4476c
	aesdec		$rndkey1,@out[2]
Packit c4476c
	aesdec		$rndkey1,@out[3]
Packit c4476c
	movups		0x30-0x78($key),$rndkey1
Packit c4476c
___
Packit c4476c
for($i=0;$i<4;$i++) {
Packit c4476c
my $rndkey = ($i&1) ? $rndkey1 : $rndkey0;
Packit c4476c
$code.=<<___;
Packit c4476c
	 cmp		`32+4*$i`(%rsp),$one
Packit c4476c
	aesdec		$rndkey,@out[0]
Packit c4476c
	aesdec		$rndkey,@out[1]
Packit c4476c
	aesdec		$rndkey,@out[2]
Packit c4476c
	 cmovge		$sink,@inptr[$i]	# cancel input
Packit c4476c
	 cmovg		$sink,@outptr[$i]	# sink output
Packit c4476c
	aesdec		$rndkey,@out[3]
Packit c4476c
	movups		`0x40+16*$i-0x78`($key),$rndkey
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	 movdqa		$counters,$mask
Packit c4476c
	aesdec		$rndkey0,@out[0]
Packit c4476c
	prefetcht0	15(@outptr[0],$offset)	# prefetch output
Packit c4476c
	prefetcht0	15(@outptr[1],$offset)
Packit c4476c
	aesdec		$rndkey0,@out[1]
Packit c4476c
	prefetcht0	15(@outptr[2],$offset)
Packit c4476c
	prefetcht0	15(@outptr[3],$offset)
Packit c4476c
	aesdec		$rndkey0,@out[2]
Packit c4476c
	aesdec		$rndkey0,@out[3]
Packit c4476c
	movups		0x80-0x78($key),$rndkey0
Packit c4476c
	 pxor		$zero,$zero
Packit c4476c
Packit c4476c
	aesdec		$rndkey1,@out[0]
Packit c4476c
	 pcmpgtd	$zero,$mask
Packit c4476c
	 movdqu		-0x78($key),$zero	# reload 0-round key
Packit c4476c
	aesdec		$rndkey1,@out[1]
Packit c4476c
	 paddd		$mask,$counters		# decrement counters
Packit c4476c
	 movdqa		$counters,32(%rsp)	# update counters
Packit c4476c
	aesdec		$rndkey1,@out[2]
Packit c4476c
	aesdec		$rndkey1,@out[3]
Packit c4476c
	movups		0x90-0x78($key),$rndkey1
Packit c4476c
Packit c4476c
	cmp	\$11,$rounds
Packit c4476c
Packit c4476c
	aesdec		$rndkey0,@out[0]
Packit c4476c
	aesdec		$rndkey0,@out[1]
Packit c4476c
	aesdec		$rndkey0,@out[2]
Packit c4476c
	aesdec		$rndkey0,@out[3]
Packit c4476c
	movups		0xa0-0x78($key),$rndkey0
Packit c4476c
Packit c4476c
	jb	.Ldec4x_tail
Packit c4476c
Packit c4476c
	aesdec		$rndkey1,@out[0]
Packit c4476c
	aesdec		$rndkey1,@out[1]
Packit c4476c
	aesdec		$rndkey1,@out[2]
Packit c4476c
	aesdec		$rndkey1,@out[3]
Packit c4476c
	movups		0xb0-0x78($key),$rndkey1
Packit c4476c
Packit c4476c
	aesdec		$rndkey0,@out[0]
Packit c4476c
	aesdec		$rndkey0,@out[1]
Packit c4476c
	aesdec		$rndkey0,@out[2]
Packit c4476c
	aesdec		$rndkey0,@out[3]
Packit c4476c
	movups		0xc0-0x78($key),$rndkey0
Packit c4476c
Packit c4476c
	je	.Ldec4x_tail
Packit c4476c
Packit c4476c
	aesdec		$rndkey1,@out[0]
Packit c4476c
	aesdec		$rndkey1,@out[1]
Packit c4476c
	aesdec		$rndkey1,@out[2]
Packit c4476c
	aesdec		$rndkey1,@out[3]
Packit c4476c
	movups		0xd0-0x78($key),$rndkey1
Packit c4476c
Packit c4476c
	aesdec		$rndkey0,@out[0]
Packit c4476c
	aesdec		$rndkey0,@out[1]
Packit c4476c
	aesdec		$rndkey0,@out[2]
Packit c4476c
	aesdec		$rndkey0,@out[3]
Packit c4476c
	movups		0xe0-0x78($key),$rndkey0
Packit c4476c
	jmp	.Ldec4x_tail
Packit c4476c
Packit c4476c
.align	32
Packit c4476c
.Ldec4x_tail:
Packit c4476c
	aesdec		$rndkey1,@out[0]
Packit c4476c
	aesdec		$rndkey1,@out[1]
Packit c4476c
	aesdec		$rndkey1,@out[2]
Packit c4476c
	 pxor		$rndkey0,@inp[0]
Packit c4476c
	 pxor		$rndkey0,@inp[1]
Packit c4476c
	aesdec		$rndkey1,@out[3]
Packit c4476c
	movdqu		0x10-0x78($key),$rndkey1
Packit c4476c
	 pxor		$rndkey0,@inp[2]
Packit c4476c
	 pxor		$rndkey0,@inp[3]
Packit c4476c
	movdqu		0x20-0x78($key),$rndkey0
Packit c4476c
Packit c4476c
	aesdeclast	@inp[0],@out[0]
Packit c4476c
	aesdeclast	@inp[1],@out[1]
Packit c4476c
	 movdqu		-16(@inptr[0],$offset),@inp[0]	# load next IV
Packit c4476c
	 movdqu		-16(@inptr[1],$offset),@inp[1]
Packit c4476c
	aesdeclast	@inp[2],@out[2]
Packit c4476c
	aesdeclast	@inp[3],@out[3]
Packit c4476c
	 movdqu		-16(@inptr[2],$offset),@inp[2]
Packit c4476c
	 movdqu		-16(@inptr[3],$offset),@inp[3]
Packit c4476c
Packit c4476c
	movups		@out[0],-16(@outptr[0],$offset)
Packit c4476c
	 movdqu		(@inptr[0],$offset),@out[0]
Packit c4476c
	movups		@out[1],-16(@outptr[1],$offset)
Packit c4476c
	 movdqu		(@inptr[1],$offset),@out[1]
Packit c4476c
	 pxor		$zero,@out[0]
Packit c4476c
	movups		@out[2],-16(@outptr[2],$offset)
Packit c4476c
	 movdqu		(@inptr[2],$offset),@out[2]
Packit c4476c
	 pxor		$zero,@out[1]
Packit c4476c
	movups		@out[3],-16(@outptr[3],$offset)
Packit c4476c
	 movdqu		(@inptr[3],$offset),@out[3]
Packit c4476c
	 pxor		$zero,@out[2]
Packit c4476c
	 pxor		$zero,@out[3]
Packit c4476c
Packit c4476c
	dec	$num
Packit c4476c
	jnz	.Loop_dec4x
Packit c4476c
Packit c4476c
	mov	16(%rsp),%rax			# original %rsp
Packit c4476c
.cfi_def_cfa	%rax,8
Packit c4476c
	mov	24(%rsp),$num
Packit c4476c
Packit c4476c
	lea	`40*4`($inp),$inp
Packit c4476c
	dec	$num
Packit c4476c
	jnz	.Ldec4x_loop_grande
Packit c4476c
Packit c4476c
.Ldec4x_done:
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($win64);
Packit c4476c
	movaps	-0xd8(%rax),%xmm6
Packit c4476c
	movaps	-0xc8(%rax),%xmm7
Packit c4476c
	movaps	-0xb8(%rax),%xmm8
Packit c4476c
	movaps	-0xa8(%rax),%xmm9
Packit c4476c
	movaps	-0x98(%rax),%xmm10
Packit c4476c
	movaps	-0x88(%rax),%xmm11
Packit c4476c
	movaps	-0x78(%rax),%xmm12
Packit c4476c
	#movaps	-0x68(%rax),%xmm13
Packit c4476c
	#movaps	-0x58(%rax),%xmm14
Packit c4476c
	#movaps	-0x48(%rax),%xmm15
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	mov	-48(%rax),%r15
Packit c4476c
.cfi_restore	%r15
Packit c4476c
	mov	-40(%rax),%r14
Packit c4476c
.cfi_restore	%r14
Packit c4476c
	mov	-32(%rax),%r13
Packit c4476c
.cfi_restore	%r13
Packit c4476c
	mov	-24(%rax),%r12
Packit c4476c
.cfi_restore	%r12
Packit c4476c
	mov	-16(%rax),%rbp
Packit c4476c
.cfi_restore	%rbp
Packit c4476c
	mov	-8(%rax),%rbx
Packit c4476c
.cfi_restore	%rbx
Packit c4476c
	lea	(%rax),%rsp
Packit c4476c
.cfi_def_cfa_register	%rsp
Packit c4476c
.Ldec4x_epilogue:
Packit c4476c
	ret
Packit c4476c
.cfi_endproc
Packit c4476c
.size	aesni_multi_cbc_decrypt,.-aesni_multi_cbc_decrypt
Packit c4476c
___
Packit c4476c
Packit c4476c
						if ($avx) {{{
Packit c4476c
my @ptr=map("%r$_",(8..15));
Packit c4476c
my $offload=$sink;
Packit c4476c
Packit c4476c
my @out=map("%xmm$_",(2..9));
Packit c4476c
my @inp=map("%xmm$_",(10..13));
Packit c4476c
my ($counters,$zero)=("%xmm14","%xmm15");
Packit c4476c
Packit c4476c
$code.=<<___;
Packit c4476c
.type	aesni_multi_cbc_encrypt_avx,\@function,3
Packit c4476c
.align	32
Packit c4476c
aesni_multi_cbc_encrypt_avx:
Packit c4476c
.cfi_startproc
Packit c4476c
_avx_cbc_enc_shortcut:
Packit c4476c
	mov	%rsp,%rax
Packit c4476c
.cfi_def_cfa_register	%rax
Packit c4476c
	push	%rbx
Packit c4476c
.cfi_push	%rbx
Packit c4476c
	push	%rbp
Packit c4476c
.cfi_push	%rbp
Packit c4476c
	push	%r12
Packit c4476c
.cfi_push	%r12
Packit c4476c
	push	%r13
Packit c4476c
.cfi_push	%r13
Packit c4476c
	push	%r14
Packit c4476c
.cfi_push	%r14
Packit c4476c
	push	%r15
Packit c4476c
.cfi_push	%r15
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($win64);
Packit c4476c
	lea	-0xa8(%rsp),%rsp
Packit c4476c
	movaps	%xmm6,(%rsp)
Packit c4476c
	movaps	%xmm7,0x10(%rsp)
Packit c4476c
	movaps	%xmm8,0x20(%rsp)
Packit c4476c
	movaps	%xmm9,0x30(%rsp)
Packit c4476c
	movaps	%xmm10,0x40(%rsp)
Packit c4476c
	movaps	%xmm11,0x50(%rsp)
Packit c4476c
	movaps	%xmm12,-0x78(%rax)
Packit c4476c
	movaps	%xmm13,-0x68(%rax)
Packit c4476c
	movaps	%xmm14,-0x58(%rax)
Packit c4476c
	movaps	%xmm15,-0x48(%rax)
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	# stack layout
Packit c4476c
	#
Packit c4476c
	# +0	output sink
Packit c4476c
	# +16	input sink [original %rsp and $num]
Packit c4476c
	# +32	counters
Packit c4476c
	# +64	distances between inputs and outputs
Packit c4476c
	# +128	off-load area for @inp[0..3]
Packit c4476c
Packit c4476c
	sub	\$192,%rsp
Packit c4476c
	and	\$-128,%rsp
Packit c4476c
	mov	%rax,16(%rsp)			# original %rsp
Packit c4476c
.cfi_cfa_expression	%rsp+16,deref,+8
Packit c4476c
Packit c4476c
.Lenc8x_body:
Packit c4476c
	vzeroupper
Packit c4476c
	vmovdqu	($key),$zero			# 0-round key
Packit c4476c
	lea	0x78($key),$key			# size optimization
Packit c4476c
	lea	40*4($inp),$inp
Packit c4476c
	shr	\$1,$num
Packit c4476c
Packit c4476c
.Lenc8x_loop_grande:
Packit c4476c
	#mov	$num,24(%rsp)			# original $num
Packit c4476c
	xor	$num,$num
Packit c4476c
___
Packit c4476c
for($i=0;$i<8;$i++) {
Packit c4476c
  my $temp = $i ? $offload : $offset;
Packit c4476c
    $code.=<<___;
Packit c4476c
	mov	`40*$i+16-40*4`($inp),$one	# borrow $one for number of blocks
Packit c4476c
	mov	`40*$i+0-40*4`($inp),@ptr[$i]	# input pointer
Packit c4476c
	cmp	$num,$one
Packit c4476c
	mov	`40*$i+8-40*4`($inp),$temp	# output pointer
Packit c4476c
	cmovg	$one,$num			# find maximum
Packit c4476c
	test	$one,$one
Packit c4476c
	vmovdqu	`40*$i+24-40*4`($inp),@out[$i]	# load IV
Packit c4476c
	mov	$one,`32+4*$i`(%rsp)		# initialize counters
Packit c4476c
	cmovle	%rsp,@ptr[$i]			# cancel input
Packit c4476c
	sub	@ptr[$i],$temp			# distance between input and output
Packit c4476c
	mov	$temp,`64+8*$i`(%rsp)		# initialize distances
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	test	$num,$num
Packit c4476c
	jz	.Lenc8x_done
Packit c4476c
Packit c4476c
	vmovups	0x10-0x78($key),$rndkey1
Packit c4476c
	vmovups	0x20-0x78($key),$rndkey0
Packit c4476c
	mov	0xf0-0x78($key),$rounds
Packit c4476c
Packit c4476c
	vpxor	(@ptr[0]),$zero,@inp[0]		# load inputs and xor with 0-round
Packit c4476c
	 lea	128(%rsp),$offload		# offload area
Packit c4476c
	vpxor	(@ptr[1]),$zero,@inp[1]
Packit c4476c
	vpxor	(@ptr[2]),$zero,@inp[2]
Packit c4476c
	vpxor	(@ptr[3]),$zero,@inp[3]
Packit c4476c
	 vpxor	@inp[0],@out[0],@out[0]
Packit c4476c
	vpxor	(@ptr[4]),$zero,@inp[0]
Packit c4476c
	 vpxor	@inp[1],@out[1],@out[1]
Packit c4476c
	vpxor	(@ptr[5]),$zero,@inp[1]
Packit c4476c
	 vpxor	@inp[2],@out[2],@out[2]
Packit c4476c
	vpxor	(@ptr[6]),$zero,@inp[2]
Packit c4476c
	 vpxor	@inp[3],@out[3],@out[3]
Packit c4476c
	vpxor	(@ptr[7]),$zero,@inp[3]
Packit c4476c
	 vpxor	@inp[0],@out[4],@out[4]
Packit c4476c
	mov	\$1,$one			# constant of 1
Packit c4476c
	 vpxor	@inp[1],@out[5],@out[5]
Packit c4476c
	 vpxor	@inp[2],@out[6],@out[6]
Packit c4476c
	 vpxor	@inp[3],@out[7],@out[7]
Packit c4476c
	jmp	.Loop_enc8x
Packit c4476c
Packit c4476c
.align	32
Packit c4476c
.Loop_enc8x:
Packit c4476c
___
Packit c4476c
for($i=0;$i<8;$i++) {
Packit c4476c
my $rndkey=($i&1)?$rndkey0:$rndkey1;
Packit c4476c
$code.=<<___;
Packit c4476c
	vaesenc		$rndkey,@out[0],@out[0]
Packit c4476c
	 cmp		32+4*$i(%rsp),$one
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($i);
Packit c4476c
	 mov		64+8*$i(%rsp),$offset
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	vaesenc		$rndkey,@out[1],@out[1]
Packit c4476c
	prefetcht0	31(@ptr[$i])			# prefetch input
Packit c4476c
	vaesenc		$rndkey,@out[2],@out[2]
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($i>1);
Packit c4476c
	prefetcht0	15(@ptr[$i-2])			# prefetch output
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	vaesenc		$rndkey,@out[3],@out[3]
Packit c4476c
	 lea		(@ptr[$i],$offset),$offset
Packit c4476c
	 cmovge		%rsp,@ptr[$i]			# cancel input
Packit c4476c
	vaesenc		$rndkey,@out[4],@out[4]
Packit c4476c
	 cmovg		%rsp,$offset			# sink output
Packit c4476c
	vaesenc		$rndkey,@out[5],@out[5]
Packit c4476c
	 sub		@ptr[$i],$offset
Packit c4476c
	vaesenc		$rndkey,@out[6],@out[6]
Packit c4476c
	 vpxor		16(@ptr[$i]),$zero,@inp[$i%4]	# load input and xor with 0-round
Packit c4476c
	 mov		$offset,64+8*$i(%rsp)
Packit c4476c
	vaesenc		$rndkey,@out[7],@out[7]
Packit c4476c
	vmovups		`16*(3+$i)-0x78`($key),$rndkey
Packit c4476c
	 lea		16(@ptr[$i],$offset),@ptr[$i]	# switch to output
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($i<4)
Packit c4476c
	 vmovdqu	@inp[$i%4],`16*$i`($offload)	# off-load
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	 vmovdqu	32(%rsp),$counters
Packit c4476c
	prefetcht0	15(@ptr[$i-2])			# prefetch output
Packit c4476c
	prefetcht0	15(@ptr[$i-1])
Packit c4476c
	cmp	\$11,$rounds
Packit c4476c
	jb	.Lenc8x_tail
Packit c4476c
Packit c4476c
	vaesenc		$rndkey1,@out[0],@out[0]
Packit c4476c
	vaesenc		$rndkey1,@out[1],@out[1]
Packit c4476c
	vaesenc		$rndkey1,@out[2],@out[2]
Packit c4476c
	vaesenc		$rndkey1,@out[3],@out[3]
Packit c4476c
	vaesenc		$rndkey1,@out[4],@out[4]
Packit c4476c
	vaesenc		$rndkey1,@out[5],@out[5]
Packit c4476c
	vaesenc		$rndkey1,@out[6],@out[6]
Packit c4476c
	vaesenc		$rndkey1,@out[7],@out[7]
Packit c4476c
	vmovups		0xb0-0x78($key),$rndkey1
Packit c4476c
Packit c4476c
	vaesenc		$rndkey0,@out[0],@out[0]
Packit c4476c
	vaesenc		$rndkey0,@out[1],@out[1]
Packit c4476c
	vaesenc		$rndkey0,@out[2],@out[2]
Packit c4476c
	vaesenc		$rndkey0,@out[3],@out[3]
Packit c4476c
	vaesenc		$rndkey0,@out[4],@out[4]
Packit c4476c
	vaesenc		$rndkey0,@out[5],@out[5]
Packit c4476c
	vaesenc		$rndkey0,@out[6],@out[6]
Packit c4476c
	vaesenc		$rndkey0,@out[7],@out[7]
Packit c4476c
	vmovups		0xc0-0x78($key),$rndkey0
Packit c4476c
	je	.Lenc8x_tail
Packit c4476c
Packit c4476c
	vaesenc		$rndkey1,@out[0],@out[0]
Packit c4476c
	vaesenc		$rndkey1,@out[1],@out[1]
Packit c4476c
	vaesenc		$rndkey1,@out[2],@out[2]
Packit c4476c
	vaesenc		$rndkey1,@out[3],@out[3]
Packit c4476c
	vaesenc		$rndkey1,@out[4],@out[4]
Packit c4476c
	vaesenc		$rndkey1,@out[5],@out[5]
Packit c4476c
	vaesenc		$rndkey1,@out[6],@out[6]
Packit c4476c
	vaesenc		$rndkey1,@out[7],@out[7]
Packit c4476c
	vmovups		0xd0-0x78($key),$rndkey1
Packit c4476c
Packit c4476c
	vaesenc		$rndkey0,@out[0],@out[0]
Packit c4476c
	vaesenc		$rndkey0,@out[1],@out[1]
Packit c4476c
	vaesenc		$rndkey0,@out[2],@out[2]
Packit c4476c
	vaesenc		$rndkey0,@out[3],@out[3]
Packit c4476c
	vaesenc		$rndkey0,@out[4],@out[4]
Packit c4476c
	vaesenc		$rndkey0,@out[5],@out[5]
Packit c4476c
	vaesenc		$rndkey0,@out[6],@out[6]
Packit c4476c
	vaesenc		$rndkey0,@out[7],@out[7]
Packit c4476c
	vmovups		0xe0-0x78($key),$rndkey0
Packit c4476c
Packit c4476c
.Lenc8x_tail:
Packit c4476c
	vaesenc		$rndkey1,@out[0],@out[0]
Packit c4476c
	 vpxor		$zero,$zero,$zero
Packit c4476c
	vaesenc		$rndkey1,@out[1],@out[1]
Packit c4476c
	vaesenc		$rndkey1,@out[2],@out[2]
Packit c4476c
	 vpcmpgtd	$zero,$counters,$zero
Packit c4476c
	vaesenc		$rndkey1,@out[3],@out[3]
Packit c4476c
	vaesenc		$rndkey1,@out[4],@out[4]
Packit c4476c
	 vpaddd		$counters,$zero,$zero		# decrement counters
Packit c4476c
	 vmovdqu	48(%rsp),$counters
Packit c4476c
	vaesenc		$rndkey1,@out[5],@out[5]
Packit c4476c
	 mov		64(%rsp),$offset		# pre-load 1st offset
Packit c4476c
	vaesenc		$rndkey1,@out[6],@out[6]
Packit c4476c
	vaesenc		$rndkey1,@out[7],@out[7]
Packit c4476c
	vmovups		0x10-0x78($key),$rndkey1
Packit c4476c
Packit c4476c
	vaesenclast	$rndkey0,@out[0],@out[0]
Packit c4476c
	 vmovdqa	$zero,32(%rsp)			# update counters
Packit c4476c
	 vpxor		$zero,$zero,$zero
Packit c4476c
	vaesenclast	$rndkey0,@out[1],@out[1]
Packit c4476c
	vaesenclast	$rndkey0,@out[2],@out[2]
Packit c4476c
	 vpcmpgtd	$zero,$counters,$zero
Packit c4476c
	vaesenclast	$rndkey0,@out[3],@out[3]
Packit c4476c
	vaesenclast	$rndkey0,@out[4],@out[4]
Packit c4476c
	 vpaddd		$zero,$counters,$counters	# decrement counters
Packit c4476c
	 vmovdqu	-0x78($key),$zero		# 0-round
Packit c4476c
	vaesenclast	$rndkey0,@out[5],@out[5]
Packit c4476c
	vaesenclast	$rndkey0,@out[6],@out[6]
Packit c4476c
	 vmovdqa	$counters,48(%rsp)		# update counters
Packit c4476c
	vaesenclast	$rndkey0,@out[7],@out[7]
Packit c4476c
	vmovups		0x20-0x78($key),$rndkey0
Packit c4476c
Packit c4476c
	vmovups		@out[0],-16(@ptr[0])		# write output
Packit c4476c
	 sub		$offset,@ptr[0]			# switch to input
Packit c4476c
	 vpxor		0x00($offload),@out[0],@out[0]
Packit c4476c
	vmovups		@out[1],-16(@ptr[1])
Packit c4476c
	 sub		`64+1*8`(%rsp),@ptr[1]
Packit c4476c
	 vpxor		0x10($offload),@out[1],@out[1]
Packit c4476c
	vmovups		@out[2],-16(@ptr[2])
Packit c4476c
	 sub		`64+2*8`(%rsp),@ptr[2]
Packit c4476c
	 vpxor		0x20($offload),@out[2],@out[2]
Packit c4476c
	vmovups		@out[3],-16(@ptr[3])
Packit c4476c
	 sub		`64+3*8`(%rsp),@ptr[3]
Packit c4476c
	 vpxor		0x30($offload),@out[3],@out[3]
Packit c4476c
	vmovups		@out[4],-16(@ptr[4])
Packit c4476c
	 sub		`64+4*8`(%rsp),@ptr[4]
Packit c4476c
	 vpxor		@inp[0],@out[4],@out[4]
Packit c4476c
	vmovups		@out[5],-16(@ptr[5])
Packit c4476c
	 sub		`64+5*8`(%rsp),@ptr[5]
Packit c4476c
	 vpxor		@inp[1],@out[5],@out[5]
Packit c4476c
	vmovups		@out[6],-16(@ptr[6])
Packit c4476c
	 sub		`64+6*8`(%rsp),@ptr[6]
Packit c4476c
	 vpxor		@inp[2],@out[6],@out[6]
Packit c4476c
	vmovups		@out[7],-16(@ptr[7])
Packit c4476c
	 sub		`64+7*8`(%rsp),@ptr[7]
Packit c4476c
	 vpxor		@inp[3],@out[7],@out[7]
Packit c4476c
Packit c4476c
	dec	$num
Packit c4476c
	jnz	.Loop_enc8x
Packit c4476c
Packit c4476c
	mov	16(%rsp),%rax			# original %rsp
Packit c4476c
.cfi_def_cfa	%rax,8
Packit c4476c
	#mov	24(%rsp),$num
Packit c4476c
	#lea	`40*8`($inp),$inp
Packit c4476c
	#dec	$num
Packit c4476c
	#jnz	.Lenc8x_loop_grande
Packit c4476c
Packit c4476c
.Lenc8x_done:
Packit c4476c
	vzeroupper
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($win64);
Packit c4476c
	movaps	-0xd8(%rax),%xmm6
Packit c4476c
	movaps	-0xc8(%rax),%xmm7
Packit c4476c
	movaps	-0xb8(%rax),%xmm8
Packit c4476c
	movaps	-0xa8(%rax),%xmm9
Packit c4476c
	movaps	-0x98(%rax),%xmm10
Packit c4476c
	movaps	-0x88(%rax),%xmm11
Packit c4476c
	movaps	-0x78(%rax),%xmm12
Packit c4476c
	movaps	-0x68(%rax),%xmm13
Packit c4476c
	movaps	-0x58(%rax),%xmm14
Packit c4476c
	movaps	-0x48(%rax),%xmm15
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	mov	-48(%rax),%r15
Packit c4476c
.cfi_restore	%r15
Packit c4476c
	mov	-40(%rax),%r14
Packit c4476c
.cfi_restore	%r14
Packit c4476c
	mov	-32(%rax),%r13
Packit c4476c
.cfi_restore	%r13
Packit c4476c
	mov	-24(%rax),%r12
Packit c4476c
.cfi_restore	%r12
Packit c4476c
	mov	-16(%rax),%rbp
Packit c4476c
.cfi_restore	%rbp
Packit c4476c
	mov	-8(%rax),%rbx
Packit c4476c
.cfi_restore	%rbx
Packit c4476c
	lea	(%rax),%rsp
Packit c4476c
.cfi_def_cfa_register	%rsp
Packit c4476c
.Lenc8x_epilogue:
Packit c4476c
	ret
Packit c4476c
.cfi_endproc
Packit c4476c
.size	aesni_multi_cbc_encrypt_avx,.-aesni_multi_cbc_encrypt_avx
Packit c4476c
Packit c4476c
.type	aesni_multi_cbc_decrypt_avx,\@function,3
Packit c4476c
.align	32
Packit c4476c
aesni_multi_cbc_decrypt_avx:
Packit c4476c
.cfi_startproc
Packit c4476c
_avx_cbc_dec_shortcut:
Packit c4476c
	mov	%rsp,%rax
Packit c4476c
.cfi_def_cfa_register	%rax
Packit c4476c
	push	%rbx
Packit c4476c
.cfi_push	%rbx
Packit c4476c
	push	%rbp
Packit c4476c
.cfi_push	%rbp
Packit c4476c
	push	%r12
Packit c4476c
.cfi_push	%r12
Packit c4476c
	push	%r13
Packit c4476c
.cfi_push	%r13
Packit c4476c
	push	%r14
Packit c4476c
.cfi_push	%r14
Packit c4476c
	push	%r15
Packit c4476c
.cfi_push	%r15
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($win64);
Packit c4476c
	lea	-0xa8(%rsp),%rsp
Packit c4476c
	movaps	%xmm6,(%rsp)
Packit c4476c
	movaps	%xmm7,0x10(%rsp)
Packit c4476c
	movaps	%xmm8,0x20(%rsp)
Packit c4476c
	movaps	%xmm9,0x30(%rsp)
Packit c4476c
	movaps	%xmm10,0x40(%rsp)
Packit c4476c
	movaps	%xmm11,0x50(%rsp)
Packit c4476c
	movaps	%xmm12,-0x78(%rax)
Packit c4476c
	movaps	%xmm13,-0x68(%rax)
Packit c4476c
	movaps	%xmm14,-0x58(%rax)
Packit c4476c
	movaps	%xmm15,-0x48(%rax)
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	# stack layout
Packit c4476c
	#
Packit c4476c
	# +0	output sink
Packit c4476c
	# +16	input sink [original %rsp and $num]
Packit c4476c
	# +32	counters
Packit c4476c
	# +64	distances between inputs and outputs
Packit c4476c
	# +128	off-load area for @inp[0..3]
Packit c4476c
	# +192	IV/input offload
Packit c4476c
Packit c4476c
	sub	\$256,%rsp
Packit c4476c
	and	\$-256,%rsp
Packit c4476c
	sub	\$192,%rsp
Packit c4476c
	mov	%rax,16(%rsp)			# original %rsp
Packit c4476c
.cfi_cfa_expression	%rsp+16,deref,+8
Packit c4476c
Packit c4476c
.Ldec8x_body:
Packit c4476c
	vzeroupper
Packit c4476c
	vmovdqu	($key),$zero			# 0-round key
Packit c4476c
	lea	0x78($key),$key			# size optimization
Packit c4476c
	lea	40*4($inp),$inp
Packit c4476c
	shr	\$1,$num
Packit c4476c
Packit c4476c
.Ldec8x_loop_grande:
Packit c4476c
	#mov	$num,24(%rsp)			# original $num
Packit c4476c
	xor	$num,$num
Packit c4476c
___
Packit c4476c
for($i=0;$i<8;$i++) {
Packit c4476c
  my $temp = $i ? $offload : $offset;
Packit c4476c
    $code.=<<___;
Packit c4476c
	mov	`40*$i+16-40*4`($inp),$one	# borrow $one for number of blocks
Packit c4476c
	mov	`40*$i+0-40*4`($inp),@ptr[$i]	# input pointer
Packit c4476c
	cmp	$num,$one
Packit c4476c
	mov	`40*$i+8-40*4`($inp),$temp	# output pointer
Packit c4476c
	cmovg	$one,$num			# find maximum
Packit c4476c
	test	$one,$one
Packit c4476c
	vmovdqu	`40*$i+24-40*4`($inp),@out[$i]	# load IV
Packit c4476c
	mov	$one,`32+4*$i`(%rsp)		# initialize counters
Packit c4476c
	cmovle	%rsp,@ptr[$i]			# cancel input
Packit c4476c
	sub	@ptr[$i],$temp			# distance between input and output
Packit c4476c
	mov	$temp,`64+8*$i`(%rsp)		# initialize distances
Packit c4476c
	vmovdqu	@out[$i],`192+16*$i`(%rsp)	# offload IV
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	test	$num,$num
Packit c4476c
	jz	.Ldec8x_done
Packit c4476c
Packit c4476c
	vmovups	0x10-0x78($key),$rndkey1
Packit c4476c
	vmovups	0x20-0x78($key),$rndkey0
Packit c4476c
	mov	0xf0-0x78($key),$rounds
Packit c4476c
	 lea	192+128(%rsp),$offload		# offload area
Packit c4476c
Packit c4476c
	vmovdqu	(@ptr[0]),@out[0]		# load inputs
Packit c4476c
	vmovdqu	(@ptr[1]),@out[1]
Packit c4476c
	vmovdqu	(@ptr[2]),@out[2]
Packit c4476c
	vmovdqu	(@ptr[3]),@out[3]
Packit c4476c
	vmovdqu	(@ptr[4]),@out[4]
Packit c4476c
	vmovdqu	(@ptr[5]),@out[5]
Packit c4476c
	vmovdqu	(@ptr[6]),@out[6]
Packit c4476c
	vmovdqu	(@ptr[7]),@out[7]
Packit c4476c
	vmovdqu	@out[0],0x00($offload)		# offload inputs
Packit c4476c
	vpxor	$zero,@out[0],@out[0]		# xor inputs with 0-round
Packit c4476c
	vmovdqu	@out[1],0x10($offload)
Packit c4476c
	vpxor	$zero,@out[1],@out[1]
Packit c4476c
	vmovdqu	@out[2],0x20($offload)
Packit c4476c
	vpxor	$zero,@out[2],@out[2]
Packit c4476c
	vmovdqu	@out[3],0x30($offload)
Packit c4476c
	vpxor	$zero,@out[3],@out[3]
Packit c4476c
	vmovdqu	@out[4],0x40($offload)
Packit c4476c
	vpxor	$zero,@out[4],@out[4]
Packit c4476c
	vmovdqu	@out[5],0x50($offload)
Packit c4476c
	vpxor	$zero,@out[5],@out[5]
Packit c4476c
	vmovdqu	@out[6],0x60($offload)
Packit c4476c
	vpxor	$zero,@out[6],@out[6]
Packit c4476c
	vmovdqu	@out[7],0x70($offload)
Packit c4476c
	vpxor	$zero,@out[7],@out[7]
Packit c4476c
	xor	\$0x80,$offload
Packit c4476c
	mov	\$1,$one			# constant of 1
Packit c4476c
	jmp	.Loop_dec8x
Packit c4476c
Packit c4476c
.align	32
Packit c4476c
.Loop_dec8x:
Packit c4476c
___
Packit c4476c
for($i=0;$i<8;$i++) {
Packit c4476c
my $rndkey=($i&1)?$rndkey0:$rndkey1;
Packit c4476c
$code.=<<___;
Packit c4476c
	vaesdec		$rndkey,@out[0],@out[0]
Packit c4476c
	 cmp		32+4*$i(%rsp),$one
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($i);
Packit c4476c
	 mov		64+8*$i(%rsp),$offset
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	vaesdec		$rndkey,@out[1],@out[1]
Packit c4476c
	prefetcht0	31(@ptr[$i])			# prefetch input
Packit c4476c
	vaesdec		$rndkey,@out[2],@out[2]
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($i>1);
Packit c4476c
	prefetcht0	15(@ptr[$i-2])			# prefetch output
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	vaesdec		$rndkey,@out[3],@out[3]
Packit c4476c
	 lea		(@ptr[$i],$offset),$offset
Packit c4476c
	 cmovge		%rsp,@ptr[$i]			# cancel input
Packit c4476c
	vaesdec		$rndkey,@out[4],@out[4]
Packit c4476c
	 cmovg		%rsp,$offset			# sink output
Packit c4476c
	vaesdec		$rndkey,@out[5],@out[5]
Packit c4476c
	 sub		@ptr[$i],$offset
Packit c4476c
	vaesdec		$rndkey,@out[6],@out[6]
Packit c4476c
	 vmovdqu	16(@ptr[$i]),@inp[$i%4]		# load input
Packit c4476c
	 mov		$offset,64+8*$i(%rsp)
Packit c4476c
	vaesdec		$rndkey,@out[7],@out[7]
Packit c4476c
	vmovups		`16*(3+$i)-0x78`($key),$rndkey
Packit c4476c
	 lea		16(@ptr[$i],$offset),@ptr[$i]	# switch to output
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($i<4);
Packit c4476c
	 vmovdqu	@inp[$i%4],`128+16*$i`(%rsp)	# off-load
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	 vmovdqu	32(%rsp),$counters
Packit c4476c
	prefetcht0	15(@ptr[$i-2])			# prefetch output
Packit c4476c
	prefetcht0	15(@ptr[$i-1])
Packit c4476c
	cmp	\$11,$rounds
Packit c4476c
	jb	.Ldec8x_tail
Packit c4476c
Packit c4476c
	vaesdec		$rndkey1,@out[0],@out[0]
Packit c4476c
	vaesdec		$rndkey1,@out[1],@out[1]
Packit c4476c
	vaesdec		$rndkey1,@out[2],@out[2]
Packit c4476c
	vaesdec		$rndkey1,@out[3],@out[3]
Packit c4476c
	vaesdec		$rndkey1,@out[4],@out[4]
Packit c4476c
	vaesdec		$rndkey1,@out[5],@out[5]
Packit c4476c
	vaesdec		$rndkey1,@out[6],@out[6]
Packit c4476c
	vaesdec		$rndkey1,@out[7],@out[7]
Packit c4476c
	vmovups		0xb0-0x78($key),$rndkey1
Packit c4476c
Packit c4476c
	vaesdec		$rndkey0,@out[0],@out[0]
Packit c4476c
	vaesdec		$rndkey0,@out[1],@out[1]
Packit c4476c
	vaesdec		$rndkey0,@out[2],@out[2]
Packit c4476c
	vaesdec		$rndkey0,@out[3],@out[3]
Packit c4476c
	vaesdec		$rndkey0,@out[4],@out[4]
Packit c4476c
	vaesdec		$rndkey0,@out[5],@out[5]
Packit c4476c
	vaesdec		$rndkey0,@out[6],@out[6]
Packit c4476c
	vaesdec		$rndkey0,@out[7],@out[7]
Packit c4476c
	vmovups		0xc0-0x78($key),$rndkey0
Packit c4476c
	je	.Ldec8x_tail
Packit c4476c
Packit c4476c
	vaesdec		$rndkey1,@out[0],@out[0]
Packit c4476c
	vaesdec		$rndkey1,@out[1],@out[1]
Packit c4476c
	vaesdec		$rndkey1,@out[2],@out[2]
Packit c4476c
	vaesdec		$rndkey1,@out[3],@out[3]
Packit c4476c
	vaesdec		$rndkey1,@out[4],@out[4]
Packit c4476c
	vaesdec		$rndkey1,@out[5],@out[5]
Packit c4476c
	vaesdec		$rndkey1,@out[6],@out[6]
Packit c4476c
	vaesdec		$rndkey1,@out[7],@out[7]
Packit c4476c
	vmovups		0xd0-0x78($key),$rndkey1
Packit c4476c
Packit c4476c
	vaesdec		$rndkey0,@out[0],@out[0]
Packit c4476c
	vaesdec		$rndkey0,@out[1],@out[1]
Packit c4476c
	vaesdec		$rndkey0,@out[2],@out[2]
Packit c4476c
	vaesdec		$rndkey0,@out[3],@out[3]
Packit c4476c
	vaesdec		$rndkey0,@out[4],@out[4]
Packit c4476c
	vaesdec		$rndkey0,@out[5],@out[5]
Packit c4476c
	vaesdec		$rndkey0,@out[6],@out[6]
Packit c4476c
	vaesdec		$rndkey0,@out[7],@out[7]
Packit c4476c
	vmovups		0xe0-0x78($key),$rndkey0
Packit c4476c
Packit c4476c
.Ldec8x_tail:
Packit c4476c
	vaesdec		$rndkey1,@out[0],@out[0]
Packit c4476c
	 vpxor		$zero,$zero,$zero
Packit c4476c
	vaesdec		$rndkey1,@out[1],@out[1]
Packit c4476c
	vaesdec		$rndkey1,@out[2],@out[2]
Packit c4476c
	 vpcmpgtd	$zero,$counters,$zero
Packit c4476c
	vaesdec		$rndkey1,@out[3],@out[3]
Packit c4476c
	vaesdec		$rndkey1,@out[4],@out[4]
Packit c4476c
	 vpaddd		$counters,$zero,$zero		# decrement counters
Packit c4476c
	 vmovdqu	48(%rsp),$counters
Packit c4476c
	vaesdec		$rndkey1,@out[5],@out[5]
Packit c4476c
	 mov		64(%rsp),$offset		# pre-load 1st offset
Packit c4476c
	vaesdec		$rndkey1,@out[6],@out[6]
Packit c4476c
	vaesdec		$rndkey1,@out[7],@out[7]
Packit c4476c
	vmovups		0x10-0x78($key),$rndkey1
Packit c4476c
Packit c4476c
	vaesdeclast	$rndkey0,@out[0],@out[0]
Packit c4476c
	 vmovdqa	$zero,32(%rsp)			# update counters
Packit c4476c
	 vpxor		$zero,$zero,$zero
Packit c4476c
	vaesdeclast	$rndkey0,@out[1],@out[1]
Packit c4476c
	vpxor		0x00($offload),@out[0],@out[0]	# xor with IV
Packit c4476c
	vaesdeclast	$rndkey0,@out[2],@out[2]
Packit c4476c
	vpxor		0x10($offload),@out[1],@out[1]
Packit c4476c
	 vpcmpgtd	$zero,$counters,$zero
Packit c4476c
	vaesdeclast	$rndkey0,@out[3],@out[3]
Packit c4476c
	vpxor		0x20($offload),@out[2],@out[2]
Packit c4476c
	vaesdeclast	$rndkey0,@out[4],@out[4]
Packit c4476c
	vpxor		0x30($offload),@out[3],@out[3]
Packit c4476c
	 vpaddd		$zero,$counters,$counters	# decrement counters
Packit c4476c
	 vmovdqu	-0x78($key),$zero		# 0-round
Packit c4476c
	vaesdeclast	$rndkey0,@out[5],@out[5]
Packit c4476c
	vpxor		0x40($offload),@out[4],@out[4]
Packit c4476c
	vaesdeclast	$rndkey0,@out[6],@out[6]
Packit c4476c
	vpxor		0x50($offload),@out[5],@out[5]
Packit c4476c
	 vmovdqa	$counters,48(%rsp)		# update counters
Packit c4476c
	vaesdeclast	$rndkey0,@out[7],@out[7]
Packit c4476c
	vpxor		0x60($offload),@out[6],@out[6]
Packit c4476c
	vmovups		0x20-0x78($key),$rndkey0
Packit c4476c
Packit c4476c
	vmovups		@out[0],-16(@ptr[0])		# write output
Packit c4476c
	 sub		$offset,@ptr[0]			# switch to input
Packit c4476c
	 vmovdqu	128+0(%rsp),@out[0]
Packit c4476c
	vpxor		0x70($offload),@out[7],@out[7]
Packit c4476c
	vmovups		@out[1],-16(@ptr[1])
Packit c4476c
	 sub		`64+1*8`(%rsp),@ptr[1]
Packit c4476c
	 vmovdqu	@out[0],0x00($offload)
Packit c4476c
	 vpxor		$zero,@out[0],@out[0]
Packit c4476c
	 vmovdqu	128+16(%rsp),@out[1]
Packit c4476c
	vmovups		@out[2],-16(@ptr[2])
Packit c4476c
	 sub		`64+2*8`(%rsp),@ptr[2]
Packit c4476c
	 vmovdqu	@out[1],0x10($offload)
Packit c4476c
	 vpxor		$zero,@out[1],@out[1]
Packit c4476c
	 vmovdqu	128+32(%rsp),@out[2]
Packit c4476c
	vmovups		@out[3],-16(@ptr[3])
Packit c4476c
	 sub		`64+3*8`(%rsp),@ptr[3]
Packit c4476c
	 vmovdqu	@out[2],0x20($offload)
Packit c4476c
	 vpxor		$zero,@out[2],@out[2]
Packit c4476c
	 vmovdqu	128+48(%rsp),@out[3]
Packit c4476c
	vmovups		@out[4],-16(@ptr[4])
Packit c4476c
	 sub		`64+4*8`(%rsp),@ptr[4]
Packit c4476c
	 vmovdqu	@out[3],0x30($offload)
Packit c4476c
	 vpxor		$zero,@out[3],@out[3]
Packit c4476c
	 vmovdqu	@inp[0],0x40($offload)
Packit c4476c
	 vpxor		@inp[0],$zero,@out[4]
Packit c4476c
	vmovups		@out[5],-16(@ptr[5])
Packit c4476c
	 sub		`64+5*8`(%rsp),@ptr[5]
Packit c4476c
	 vmovdqu	@inp[1],0x50($offload)
Packit c4476c
	 vpxor		@inp[1],$zero,@out[5]
Packit c4476c
	vmovups		@out[6],-16(@ptr[6])
Packit c4476c
	 sub		`64+6*8`(%rsp),@ptr[6]
Packit c4476c
	 vmovdqu	@inp[2],0x60($offload)
Packit c4476c
	 vpxor		@inp[2],$zero,@out[6]
Packit c4476c
	vmovups		@out[7],-16(@ptr[7])
Packit c4476c
	 sub		`64+7*8`(%rsp),@ptr[7]
Packit c4476c
	 vmovdqu	@inp[3],0x70($offload)
Packit c4476c
	 vpxor		@inp[3],$zero,@out[7]
Packit c4476c
Packit c4476c
	xor	\$128,$offload
Packit c4476c
	dec	$num
Packit c4476c
	jnz	.Loop_dec8x
Packit c4476c
Packit c4476c
	mov	16(%rsp),%rax			# original %rsp
Packit c4476c
.cfi_def_cfa	%rax,8
Packit c4476c
	#mov	24(%rsp),$num
Packit c4476c
	#lea	`40*8`($inp),$inp
Packit c4476c
	#dec	$num
Packit c4476c
	#jnz	.Ldec8x_loop_grande
Packit c4476c
Packit c4476c
.Ldec8x_done:
Packit c4476c
	vzeroupper
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($win64);
Packit c4476c
	movaps	-0xd8(%rax),%xmm6
Packit c4476c
	movaps	-0xc8(%rax),%xmm7
Packit c4476c
	movaps	-0xb8(%rax),%xmm8
Packit c4476c
	movaps	-0xa8(%rax),%xmm9
Packit c4476c
	movaps	-0x98(%rax),%xmm10
Packit c4476c
	movaps	-0x88(%rax),%xmm11
Packit c4476c
	movaps	-0x78(%rax),%xmm12
Packit c4476c
	movaps	-0x68(%rax),%xmm13
Packit c4476c
	movaps	-0x58(%rax),%xmm14
Packit c4476c
	movaps	-0x48(%rax),%xmm15
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	mov	-48(%rax),%r15
Packit c4476c
.cfi_restore	%r15
Packit c4476c
	mov	-40(%rax),%r14
Packit c4476c
.cfi_restore	%r14
Packit c4476c
	mov	-32(%rax),%r13
Packit c4476c
.cfi_restore	%r13
Packit c4476c
	mov	-24(%rax),%r12
Packit c4476c
.cfi_restore	%r12
Packit c4476c
	mov	-16(%rax),%rbp
Packit c4476c
.cfi_restore	%rbp
Packit c4476c
	mov	-8(%rax),%rbx
Packit c4476c
.cfi_restore	%rbx
Packit c4476c
	lea	(%rax),%rsp
Packit c4476c
.cfi_def_cfa_register	%rsp
Packit c4476c
.Ldec8x_epilogue:
Packit c4476c
	ret
Packit c4476c
.cfi_endproc
Packit c4476c
.size	aesni_multi_cbc_decrypt_avx,.-aesni_multi_cbc_decrypt_avx
Packit c4476c
___
Packit c4476c
						}}}
Packit c4476c
Packit c4476c
if ($win64) {
Packit c4476c
# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
Packit c4476c
#		CONTEXT *context,DISPATCHER_CONTEXT *disp)
Packit c4476c
$rec="%rcx";
Packit c4476c
$frame="%rdx";
Packit c4476c
$context="%r8";
Packit c4476c
$disp="%r9";
Packit c4476c
Packit c4476c
$code.=<<___;
Packit c4476c
.extern	__imp_RtlVirtualUnwind
Packit c4476c
.type	se_handler,\@abi-omnipotent
Packit c4476c
.align	16
Packit c4476c
se_handler:
Packit c4476c
	push	%rsi
Packit c4476c
	push	%rdi
Packit c4476c
	push	%rbx
Packit c4476c
	push	%rbp
Packit c4476c
	push	%r12
Packit c4476c
	push	%r13
Packit c4476c
	push	%r14
Packit c4476c
	push	%r15
Packit c4476c
	pushfq
Packit c4476c
	sub	\$64,%rsp
Packit c4476c
Packit c4476c
	mov	120($context),%rax	# pull context->Rax
Packit c4476c
	mov	248($context),%rbx	# pull context->Rip
Packit c4476c
Packit c4476c
	mov	8($disp),%rsi		# disp->ImageBase
Packit c4476c
	mov	56($disp),%r11		# disp->HandlerData
Packit c4476c
Packit c4476c
	mov	0(%r11),%r10d		# HandlerData[0]
Packit c4476c
	lea	(%rsi,%r10),%r10	# prologue label
Packit c4476c
	cmp	%r10,%rbx		# context->Rip<.Lprologue
Packit c4476c
	jb	.Lin_prologue
Packit c4476c
Packit c4476c
	mov	152($context),%rax	# pull context->Rsp
Packit c4476c
Packit c4476c
	mov	4(%r11),%r10d		# HandlerData[1]
Packit c4476c
	lea	(%rsi,%r10),%r10	# epilogue label
Packit c4476c
	cmp	%r10,%rbx		# context->Rip>=.Lepilogue
Packit c4476c
	jae	.Lin_prologue
Packit c4476c
Packit c4476c
	mov	16(%rax),%rax		# pull saved stack pointer
Packit c4476c
Packit c4476c
	mov	-8(%rax),%rbx
Packit c4476c
	mov	-16(%rax),%rbp
Packit c4476c
	mov	-24(%rax),%r12
Packit c4476c
	mov	-32(%rax),%r13
Packit c4476c
	mov	-40(%rax),%r14
Packit c4476c
	mov	-48(%rax),%r15
Packit c4476c
	mov	%rbx,144($context)	# restore context->Rbx
Packit c4476c
	mov	%rbp,160($context)	# restore context->Rbp
Packit c4476c
	mov	%r12,216($context)	# restore context->R12
Packit c4476c
	mov	%r13,224($context)	# restore context->R13
Packit c4476c
	mov	%r14,232($context)	# restore context->R14
Packit c4476c
	mov	%r15,240($context)	# restore context->R15
Packit c4476c
Packit c4476c
	lea	-56-10*16(%rax),%rsi
Packit c4476c
	lea	512($context),%rdi	# &context.Xmm6
Packit c4476c
	mov	\$20,%ecx
Packit c4476c
	.long	0xa548f3fc		# cld; rep movsq
Packit c4476c
Packit c4476c
.Lin_prologue:
Packit c4476c
	mov	8(%rax),%rdi
Packit c4476c
	mov	16(%rax),%rsi
Packit c4476c
	mov	%rax,152($context)	# restore context->Rsp
Packit c4476c
	mov	%rsi,168($context)	# restore context->Rsi
Packit c4476c
	mov	%rdi,176($context)	# restore context->Rdi
Packit c4476c
Packit c4476c
	mov	40($disp),%rdi		# disp->ContextRecord
Packit c4476c
	mov	$context,%rsi		# context
Packit c4476c
	mov	\$154,%ecx		# sizeof(CONTEXT)
Packit c4476c
	.long	0xa548f3fc		# cld; rep movsq
Packit c4476c
Packit c4476c
	mov	$disp,%rsi
Packit c4476c
	xor	%rcx,%rcx		# arg1, UNW_FLAG_NHANDLER
Packit c4476c
	mov	8(%rsi),%rdx		# arg2, disp->ImageBase
Packit c4476c
	mov	0(%rsi),%r8		# arg3, disp->ControlPc
Packit c4476c
	mov	16(%rsi),%r9		# arg4, disp->FunctionEntry
Packit c4476c
	mov	40(%rsi),%r10		# disp->ContextRecord
Packit c4476c
	lea	56(%rsi),%r11		# &disp->HandlerData
Packit c4476c
	lea	24(%rsi),%r12		# &disp->EstablisherFrame
Packit c4476c
	mov	%r10,32(%rsp)		# arg5
Packit c4476c
	mov	%r11,40(%rsp)		# arg6
Packit c4476c
	mov	%r12,48(%rsp)		# arg7
Packit c4476c
	mov	%rcx,56(%rsp)		# arg8, (NULL)
Packit c4476c
	call	*__imp_RtlVirtualUnwind(%rip)
Packit c4476c
Packit c4476c
	mov	\$1,%eax		# ExceptionContinueSearch
Packit c4476c
	add	\$64,%rsp
Packit c4476c
	popfq
Packit c4476c
	pop	%r15
Packit c4476c
	pop	%r14
Packit c4476c
	pop	%r13
Packit c4476c
	pop	%r12
Packit c4476c
	pop	%rbp
Packit c4476c
	pop	%rbx
Packit c4476c
	pop	%rdi
Packit c4476c
	pop	%rsi
Packit c4476c
	ret
Packit c4476c
.size	se_handler,.-se_handler
Packit c4476c
Packit c4476c
.section	.pdata
Packit c4476c
.align	4
Packit c4476c
	.rva	.LSEH_begin_aesni_multi_cbc_encrypt
Packit c4476c
	.rva	.LSEH_end_aesni_multi_cbc_encrypt
Packit c4476c
	.rva	.LSEH_info_aesni_multi_cbc_encrypt
Packit c4476c
	.rva	.LSEH_begin_aesni_multi_cbc_decrypt
Packit c4476c
	.rva	.LSEH_end_aesni_multi_cbc_decrypt
Packit c4476c
	.rva	.LSEH_info_aesni_multi_cbc_decrypt
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($avx);
Packit c4476c
	.rva	.LSEH_begin_aesni_multi_cbc_encrypt_avx
Packit c4476c
	.rva	.LSEH_end_aesni_multi_cbc_encrypt_avx
Packit c4476c
	.rva	.LSEH_info_aesni_multi_cbc_encrypt_avx
Packit c4476c
	.rva	.LSEH_begin_aesni_multi_cbc_decrypt_avx
Packit c4476c
	.rva	.LSEH_end_aesni_multi_cbc_decrypt_avx
Packit c4476c
	.rva	.LSEH_info_aesni_multi_cbc_decrypt_avx
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
.section	.xdata
Packit c4476c
.align	8
Packit c4476c
.LSEH_info_aesni_multi_cbc_encrypt:
Packit c4476c
	.byte	9,0,0,0
Packit c4476c
	.rva	se_handler
Packit c4476c
	.rva	.Lenc4x_body,.Lenc4x_epilogue		# HandlerData[]
Packit c4476c
.LSEH_info_aesni_multi_cbc_decrypt:
Packit c4476c
	.byte	9,0,0,0
Packit c4476c
	.rva	se_handler
Packit c4476c
	.rva	.Ldec4x_body,.Ldec4x_epilogue		# HandlerData[]
Packit c4476c
___
Packit c4476c
$code.=<<___ if ($avx);
Packit c4476c
.LSEH_info_aesni_multi_cbc_encrypt_avx:
Packit c4476c
	.byte	9,0,0,0
Packit c4476c
	.rva	se_handler
Packit c4476c
	.rva	.Lenc8x_body,.Lenc8x_epilogue		# HandlerData[]
Packit c4476c
.LSEH_info_aesni_multi_cbc_decrypt_avx:
Packit c4476c
	.byte	9,0,0,0
Packit c4476c
	.rva	se_handler
Packit c4476c
	.rva	.Ldec8x_body,.Ldec8x_epilogue		# HandlerData[]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
####################################################################
Packit c4476c
Packit c4476c
sub rex {
Packit c4476c
  local *opcode=shift;
Packit c4476c
  my ($dst,$src)=@_;
Packit c4476c
  my $rex=0;
Packit c4476c
Packit c4476c
    $rex|=0x04			if($dst>=8);
Packit c4476c
    $rex|=0x01			if($src>=8);
Packit c4476c
    push @opcode,$rex|0x40	if($rex);
Packit c4476c
}
Packit c4476c
Packit c4476c
sub aesni {
Packit c4476c
  my $line=shift;
Packit c4476c
  my @opcode=(0x66);
Packit c4476c
Packit c4476c
    if ($line=~/(aeskeygenassist)\s+\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
Packit c4476c
	rex(\@opcode,$4,$3);
Packit c4476c
	push @opcode,0x0f,0x3a,0xdf;
Packit c4476c
	push @opcode,0xc0|($3&7)|(($4&7)<<3);	# ModR/M
Packit c4476c
	my $c=$2;
Packit c4476c
	push @opcode,$c=~/^0/?oct($c):$c;
Packit c4476c
	return ".byte\t".join(',',@opcode);
Packit c4476c
    }
Packit c4476c
    elsif ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) {
Packit c4476c
	my %opcodelet = (
Packit c4476c
		"aesimc" => 0xdb,
Packit c4476c
		"aesenc" => 0xdc,	"aesenclast" => 0xdd,
Packit c4476c
		"aesdec" => 0xde,	"aesdeclast" => 0xdf
Packit c4476c
	);
Packit c4476c
	return undef if (!defined($opcodelet{$1}));
Packit c4476c
	rex(\@opcode,$3,$2);
Packit c4476c
	push @opcode,0x0f,0x38,$opcodelet{$1};
Packit c4476c
	push @opcode,0xc0|($2&7)|(($3&7)<<3);	# ModR/M
Packit c4476c
	return ".byte\t".join(',',@opcode);
Packit c4476c
    }
Packit c4476c
    elsif ($line=~/(aes[a-z]+)\s+([0x1-9a-fA-F]*)\(%rsp\),\s*%xmm([0-9]+)/) {
Packit c4476c
	my %opcodelet = (
Packit c4476c
		"aesenc" => 0xdc,	"aesenclast" => 0xdd,
Packit c4476c
		"aesdec" => 0xde,	"aesdeclast" => 0xdf
Packit c4476c
	);
Packit c4476c
	return undef if (!defined($opcodelet{$1}));
Packit c4476c
	my $off = $2;
Packit c4476c
	push @opcode,0x44 if ($3>=8);
Packit c4476c
	push @opcode,0x0f,0x38,$opcodelet{$1};
Packit c4476c
	push @opcode,0x44|(($3&7)<<3),0x24;	# ModR/M
Packit c4476c
	push @opcode,($off=~/^0/?oct($off):$off)&0xff;
Packit c4476c
	return ".byte\t".join(',',@opcode);
Packit c4476c
    }
Packit c4476c
    return $line;
Packit c4476c
}
Packit c4476c
Packit c4476c
$code =~ s/\`([^\`]*)\`/eval($1)/gem;
Packit c4476c
$code =~ s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/gem;
Packit c4476c
Packit c4476c
print $code;
Packit c4476c
close STDOUT or die "error closing STDOUT: $!";