Blame engines/asm/e_padlock-x86_64.pl

Packit Service 084de1
#! /usr/bin/env perl
Packit Service 084de1
# Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
Packit Service 084de1
#
Packit Service 084de1
# Licensed under the OpenSSL license (the "License").  You may not use
Packit Service 084de1
# this file except in compliance with the License.  You can obtain a copy
Packit Service 084de1
# in the file LICENSE in the source distribution or at
Packit Service 084de1
# https://www.openssl.org/source/license.html
Packit Service 084de1
Packit Service 084de1
Packit Service 084de1
# ====================================================================
Packit Service 084de1
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
Packit Service 084de1
# project. The module is, however, dual licensed under OpenSSL and
Packit Service 084de1
# CRYPTOGAMS licenses depending on where you obtain it. For further
Packit Service 084de1
# details see http://www.openssl.org/~appro/cryptogams/.
Packit Service 084de1
# ====================================================================
Packit Service 084de1
Packit Service 084de1
# September 2011
Packit Service 084de1
#
Packit Service 084de1
# Assembler helpers for Padlock engine. See even e_padlock-x86.pl for
Packit Service 084de1
# details.
Packit Service 084de1
Packit Service 084de1
$flavour = shift;
Packit Service 084de1
$output  = shift;
Packit Service 084de1
if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
Packit Service 084de1
Packit Service 084de1
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
Packit Service 084de1
Packit Service 084de1
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
Packit Service 084de1
( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
Packit Service 084de1
( $xlate="${dir}../../crypto/perlasm/x86_64-xlate.pl" and -f $xlate) or
Packit Service 084de1
die "can't locate x86_64-xlate.pl";
Packit Service 084de1
Packit Service 084de1
open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
Packit Service 084de1
*STDOUT=*OUT;
Packit Service 084de1
Packit Service 084de1
$code=".text\n";
Packit Service 084de1
Packit Service 084de1
%PADLOCK_PREFETCH=(ecb=>128, cbc=>64, ctr32=>32);	# prefetch errata
Packit Service 084de1
$PADLOCK_CHUNK=512;	# Must be a power of 2 between 32 and 2^20
Packit Service 084de1
Packit Service 084de1
$ctx="%rdx";
Packit Service 084de1
$out="%rdi";
Packit Service 084de1
$inp="%rsi";
Packit Service 084de1
$len="%rcx";
Packit Service 084de1
$chunk="%rbx";
Packit Service 084de1
Packit Service 084de1
($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order
Packit Service 084de1
                                 ("%rdi","%rsi","%rdx","%rcx"); # Unix order
Packit Service 084de1
Packit Service 084de1
$code.=<<___;
Packit Service 084de1
.globl	padlock_capability
Packit Service 084de1
.type	padlock_capability,\@abi-omnipotent
Packit Service 084de1
.align	16
Packit Service 084de1
padlock_capability:
Packit Service 084de1
	mov	%rbx,%r8
Packit Service 084de1
	xor	%eax,%eax
Packit Service 084de1
	cpuid
Packit Service 084de1
	xor	%eax,%eax
Packit Service 084de1
	cmp	\$`"0x".unpack("H*",'tneC')`,%ebx
Packit Service 084de1
	jne	.Lzhaoxin
Packit Service 084de1
	cmp	\$`"0x".unpack("H*",'Hrua')`,%edx
Packit Service 084de1
	jne	.Lnoluck
Packit Service 084de1
	cmp	\$`"0x".unpack("H*",'slua')`,%ecx
Packit Service 084de1
	jne	.Lnoluck
Packit Service 084de1
	jmp	.LzhaoxinEnd
Packit Service 084de1
.Lzhaoxin:
Packit Service 084de1
	cmp	\$`"0x".unpack("H*",'hS  ')`,%ebx
Packit Service 084de1
	jne	.Lnoluck
Packit Service 084de1
	cmp	\$`"0x".unpack("H*",'hgna')`,%edx
Packit Service 084de1
	jne	.Lnoluck
Packit Service 084de1
	cmp	\$`"0x".unpack("H*",'  ia')`,%ecx
Packit Service 084de1
	jne	.Lnoluck
Packit Service 084de1
.LzhaoxinEnd:
Packit Service 084de1
	mov	\$0xC0000000,%eax
Packit Service 084de1
	cpuid
Packit Service 084de1
	mov	%eax,%edx
Packit Service 084de1
	xor	%eax,%eax
Packit Service 084de1
	cmp	\$0xC0000001,%edx
Packit Service 084de1
	jb	.Lnoluck
Packit Service 084de1
	mov	\$0xC0000001,%eax
Packit Service 084de1
	cpuid
Packit Service 084de1
	mov	%edx,%eax
Packit Service 084de1
	and	\$0xffffffef,%eax
Packit Service 084de1
	or	\$0x10,%eax		# set Nano bit#4
Packit Service 084de1
.Lnoluck:
Packit Service 084de1
	mov	%r8,%rbx
Packit Service 084de1
	ret
Packit Service 084de1
.size	padlock_capability,.-padlock_capability
Packit Service 084de1
Packit Service 084de1
.globl	padlock_key_bswap
Packit Service 084de1
.type	padlock_key_bswap,\@abi-omnipotent,0
Packit Service 084de1
.align	16
Packit Service 084de1
padlock_key_bswap:
Packit Service 084de1
	mov	240($arg1),%edx
Packit Service 084de1
.Lbswap_loop:
Packit Service 084de1
	mov	($arg1),%eax
Packit Service 084de1
	bswap	%eax
Packit Service 084de1
	mov	%eax,($arg1)
Packit Service 084de1
	lea	4($arg1),$arg1
Packit Service 084de1
	sub	\$1,%edx
Packit Service 084de1
	jnz	.Lbswap_loop
Packit Service 084de1
	ret
Packit Service 084de1
.size	padlock_key_bswap,.-padlock_key_bswap
Packit Service 084de1
Packit Service 084de1
.globl	padlock_verify_context
Packit Service 084de1
.type	padlock_verify_context,\@abi-omnipotent
Packit Service 084de1
.align	16
Packit Service 084de1
padlock_verify_context:
Packit Service 084de1
	mov	$arg1,$ctx
Packit Service 084de1
	pushf
Packit Service 084de1
	lea	.Lpadlock_saved_context(%rip),%rax
Packit Service 084de1
	call	_padlock_verify_ctx
Packit Service 084de1
	lea	8(%rsp),%rsp
Packit Service 084de1
	ret
Packit Service 084de1
.size	padlock_verify_context,.-padlock_verify_context
Packit Service 084de1
Packit Service 084de1
.type	_padlock_verify_ctx,\@abi-omnipotent
Packit Service 084de1
.align	16
Packit Service 084de1
_padlock_verify_ctx:
Packit Service 084de1
	mov	8(%rsp),%r8
Packit Service 084de1
	bt	\$30,%r8
Packit Service 084de1
	jnc	.Lverified
Packit Service 084de1
	cmp	(%rax),$ctx
Packit Service 084de1
	je	.Lverified
Packit Service 084de1
	pushf
Packit Service 084de1
	popf
Packit Service 084de1
.Lverified:
Packit Service 084de1
	mov	$ctx,(%rax)
Packit Service 084de1
	ret
Packit Service 084de1
.size	_padlock_verify_ctx,.-_padlock_verify_ctx
Packit Service 084de1
Packit Service 084de1
.globl	padlock_reload_key
Packit Service 084de1
.type	padlock_reload_key,\@abi-omnipotent
Packit Service 084de1
.align	16
Packit Service 084de1
padlock_reload_key:
Packit Service 084de1
	pushf
Packit Service 084de1
	popf
Packit Service 084de1
	ret
Packit Service 084de1
.size	padlock_reload_key,.-padlock_reload_key
Packit Service 084de1
Packit Service 084de1
.globl	padlock_aes_block
Packit Service 084de1
.type	padlock_aes_block,\@function,3
Packit Service 084de1
.align	16
Packit Service 084de1
padlock_aes_block:
Packit Service 084de1
	mov	%rbx,%r8
Packit Service 084de1
	mov	\$1,$len
Packit Service 084de1
	lea	32($ctx),%rbx		# key
Packit Service 084de1
	lea	16($ctx),$ctx		# control word
Packit Service 084de1
	.byte	0xf3,0x0f,0xa7,0xc8	# rep xcryptecb
Packit Service 084de1
	mov	%r8,%rbx
Packit Service 084de1
	ret
Packit Service 084de1
.size	padlock_aes_block,.-padlock_aes_block
Packit Service 084de1
Packit Service 084de1
.globl	padlock_xstore
Packit Service 084de1
.type	padlock_xstore,\@function,2
Packit Service 084de1
.align	16
Packit Service 084de1
padlock_xstore:
Packit Service 084de1
	mov	%esi,%edx
Packit Service 084de1
	.byte	0x0f,0xa7,0xc0		# xstore
Packit Service 084de1
	ret
Packit Service 084de1
.size	padlock_xstore,.-padlock_xstore
Packit Service 084de1
Packit Service 084de1
.globl	padlock_sha1_oneshot
Packit Service 084de1
.type	padlock_sha1_oneshot,\@function,3
Packit Service 084de1
.align	16
Packit Service 084de1
padlock_sha1_oneshot:
Packit Service 084de1
	mov	%rdx,%rcx
Packit Service 084de1
	mov	%rdi,%rdx		# put aside %rdi
Packit Service 084de1
	movups	(%rdi),%xmm0		# copy-in context
Packit Service 084de1
	sub	\$128+8,%rsp
Packit Service 084de1
	mov	16(%rdi),%eax
Packit Service 084de1
	movaps	%xmm0,(%rsp)
Packit Service 084de1
	mov	%rsp,%rdi
Packit Service 084de1
	mov	%eax,16(%rsp)
Packit Service 084de1
	xor	%rax,%rax
Packit Service 084de1
	.byte	0xf3,0x0f,0xa6,0xc8	# rep xsha1
Packit Service 084de1
	movaps	(%rsp),%xmm0
Packit Service 084de1
	mov	16(%rsp),%eax
Packit Service 084de1
	add	\$128+8,%rsp
Packit Service 084de1
	movups	%xmm0,(%rdx)		# copy-out context
Packit Service 084de1
	mov	%eax,16(%rdx)
Packit Service 084de1
	ret
Packit Service 084de1
.size	padlock_sha1_oneshot,.-padlock_sha1_oneshot
Packit Service 084de1
Packit Service 084de1
.globl	padlock_sha1_blocks
Packit Service 084de1
.type	padlock_sha1_blocks,\@function,3
Packit Service 084de1
.align	16
Packit Service 084de1
padlock_sha1_blocks:
Packit Service 084de1
	mov	%rdx,%rcx
Packit Service 084de1
	mov	%rdi,%rdx		# put aside %rdi
Packit Service 084de1
	movups	(%rdi),%xmm0		# copy-in context
Packit Service 084de1
	sub	\$128+8,%rsp
Packit Service 084de1
	mov	16(%rdi),%eax
Packit Service 084de1
	movaps	%xmm0,(%rsp)
Packit Service 084de1
	mov	%rsp,%rdi
Packit Service 084de1
	mov	%eax,16(%rsp)
Packit Service 084de1
	mov	\$-1,%rax
Packit Service 084de1
	.byte	0xf3,0x0f,0xa6,0xc8	# rep xsha1
Packit Service 084de1
	movaps	(%rsp),%xmm0
Packit Service 084de1
	mov	16(%rsp),%eax
Packit Service 084de1
	add	\$128+8,%rsp
Packit Service 084de1
	movups	%xmm0,(%rdx)		# copy-out context
Packit Service 084de1
	mov	%eax,16(%rdx)
Packit Service 084de1
	ret
Packit Service 084de1
.size	padlock_sha1_blocks,.-padlock_sha1_blocks
Packit Service 084de1
Packit Service 084de1
.globl	padlock_sha256_oneshot
Packit Service 084de1
.type	padlock_sha256_oneshot,\@function,3
Packit Service 084de1
.align	16
Packit Service 084de1
padlock_sha256_oneshot:
Packit Service 084de1
	mov	%rdx,%rcx
Packit Service 084de1
	mov	%rdi,%rdx		# put aside %rdi
Packit Service 084de1
	movups	(%rdi),%xmm0		# copy-in context
Packit Service 084de1
	sub	\$128+8,%rsp
Packit Service 084de1
	movups	16(%rdi),%xmm1
Packit Service 084de1
	movaps	%xmm0,(%rsp)
Packit Service 084de1
	mov	%rsp,%rdi
Packit Service 084de1
	movaps	%xmm1,16(%rsp)
Packit Service 084de1
	xor	%rax,%rax
Packit Service 084de1
	.byte	0xf3,0x0f,0xa6,0xd0	# rep xsha256
Packit Service 084de1
	movaps	(%rsp),%xmm0
Packit Service 084de1
	movaps	16(%rsp),%xmm1
Packit Service 084de1
	add	\$128+8,%rsp
Packit Service 084de1
	movups	%xmm0,(%rdx)		# copy-out context
Packit Service 084de1
	movups	%xmm1,16(%rdx)
Packit Service 084de1
	ret
Packit Service 084de1
.size	padlock_sha256_oneshot,.-padlock_sha256_oneshot
Packit Service 084de1
Packit Service 084de1
.globl	padlock_sha256_blocks
Packit Service 084de1
.type	padlock_sha256_blocks,\@function,3
Packit Service 084de1
.align	16
Packit Service 084de1
padlock_sha256_blocks:
Packit Service 084de1
	mov	%rdx,%rcx
Packit Service 084de1
	mov	%rdi,%rdx		# put aside %rdi
Packit Service 084de1
	movups	(%rdi),%xmm0		# copy-in context
Packit Service 084de1
	sub	\$128+8,%rsp
Packit Service 084de1
	movups	16(%rdi),%xmm1
Packit Service 084de1
	movaps	%xmm0,(%rsp)
Packit Service 084de1
	mov	%rsp,%rdi
Packit Service 084de1
	movaps	%xmm1,16(%rsp)
Packit Service 084de1
	mov	\$-1,%rax
Packit Service 084de1
	.byte	0xf3,0x0f,0xa6,0xd0	# rep xsha256
Packit Service 084de1
	movaps	(%rsp),%xmm0
Packit Service 084de1
	movaps	16(%rsp),%xmm1
Packit Service 084de1
	add	\$128+8,%rsp
Packit Service 084de1
	movups	%xmm0,(%rdx)		# copy-out context
Packit Service 084de1
	movups	%xmm1,16(%rdx)
Packit Service 084de1
	ret
Packit Service 084de1
.size	padlock_sha256_blocks,.-padlock_sha256_blocks
Packit Service 084de1
Packit Service 084de1
.globl	padlock_sha512_blocks
Packit Service 084de1
.type	padlock_sha512_blocks,\@function,3
Packit Service 084de1
.align	16
Packit Service 084de1
padlock_sha512_blocks:
Packit Service 084de1
	mov	%rdx,%rcx
Packit Service 084de1
	mov	%rdi,%rdx		# put aside %rdi
Packit Service 084de1
	movups	(%rdi),%xmm0		# copy-in context
Packit Service 084de1
	sub	\$128+8,%rsp
Packit Service 084de1
	movups	16(%rdi),%xmm1
Packit Service 084de1
	movups	32(%rdi),%xmm2
Packit Service 084de1
	movups	48(%rdi),%xmm3
Packit Service 084de1
	movaps	%xmm0,(%rsp)
Packit Service 084de1
	mov	%rsp,%rdi
Packit Service 084de1
	movaps	%xmm1,16(%rsp)
Packit Service 084de1
	movaps	%xmm2,32(%rsp)
Packit Service 084de1
	movaps	%xmm3,48(%rsp)
Packit Service 084de1
	.byte	0xf3,0x0f,0xa6,0xe0	# rep xha512
Packit Service 084de1
	movaps	(%rsp),%xmm0
Packit Service 084de1
	movaps	16(%rsp),%xmm1
Packit Service 084de1
	movaps	32(%rsp),%xmm2
Packit Service 084de1
	movaps	48(%rsp),%xmm3
Packit Service 084de1
	add	\$128+8,%rsp
Packit Service 084de1
	movups	%xmm0,(%rdx)		# copy-out context
Packit Service 084de1
	movups	%xmm1,16(%rdx)
Packit Service 084de1
	movups	%xmm2,32(%rdx)
Packit Service 084de1
	movups	%xmm3,48(%rdx)
Packit Service 084de1
	ret
Packit Service 084de1
.size	padlock_sha512_blocks,.-padlock_sha512_blocks
Packit Service 084de1
___
Packit Service 084de1
Packit Service 084de1
sub generate_mode {
Packit Service 084de1
my ($mode,$opcode) = @_;
Packit Service 084de1
# int padlock_$mode_encrypt(void *out, const void *inp,
Packit Service 084de1
#		struct padlock_cipher_data *ctx, size_t len);
Packit Service 084de1
$code.=<<___;
Packit Service 084de1
.globl	padlock_${mode}_encrypt
Packit Service 084de1
.type	padlock_${mode}_encrypt,\@function,4
Packit Service 084de1
.align	16
Packit Service 084de1
padlock_${mode}_encrypt:
Packit Service 084de1
	push	%rbp
Packit Service 084de1
	push	%rbx
Packit Service 084de1
Packit Service 084de1
	xor	%eax,%eax
Packit Service 084de1
	test	\$15,$ctx
Packit Service 084de1
	jnz	.L${mode}_abort
Packit Service 084de1
	test	\$15,$len
Packit Service 084de1
	jnz	.L${mode}_abort
Packit Service 084de1
	lea	.Lpadlock_saved_context(%rip),%rax
Packit Service 084de1
	pushf
Packit Service 084de1
	cld
Packit Service 084de1
	call	_padlock_verify_ctx
Packit Service 084de1
	lea	16($ctx),$ctx		# control word
Packit Service 084de1
	xor	%eax,%eax
Packit Service 084de1
	xor	%ebx,%ebx
Packit Service 084de1
	testl	\$`1<<5`,($ctx)		# align bit in control word
Packit Service 084de1
	jnz	.L${mode}_aligned
Packit Service 084de1
	test	\$0x0f,$out
Packit Service 084de1
	setz	%al			# !out_misaligned
Packit Service 084de1
	test	\$0x0f,$inp
Packit Service 084de1
	setz	%bl			# !inp_misaligned
Packit Service 084de1
	test	%ebx,%eax
Packit Service 084de1
	jnz	.L${mode}_aligned
Packit Service 084de1
	neg	%rax
Packit Service 084de1
	mov	\$$PADLOCK_CHUNK,$chunk
Packit Service 084de1
	not	%rax			# out_misaligned?-1:0
Packit Service 084de1
	lea	(%rsp),%rbp
Packit Service 084de1
	cmp	$chunk,$len
Packit Service 084de1
	cmovc	$len,$chunk		# chunk=len>PADLOCK_CHUNK?PADLOCK_CHUNK:len
Packit Service 084de1
	and	$chunk,%rax		# out_misaligned?chunk:0
Packit Service 084de1
	mov	$len,$chunk
Packit Service 084de1
	neg	%rax
Packit Service 084de1
	and	\$$PADLOCK_CHUNK-1,$chunk	# chunk%=PADLOCK_CHUNK
Packit Service 084de1
	lea	(%rax,%rbp),%rsp
Packit Service 084de1
	mov	\$$PADLOCK_CHUNK,%rax
Packit Service 084de1
	cmovz	%rax,$chunk			# chunk=chunk?:PADLOCK_CHUNK
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___				if ($mode eq "ctr32");
Packit Service 084de1
.L${mode}_reenter:
Packit Service 084de1
	mov	-4($ctx),%eax		# pull 32-bit counter
Packit Service 084de1
	bswap	%eax
Packit Service 084de1
	neg	%eax
Packit Service 084de1
	and	\$`$PADLOCK_CHUNK/16-1`,%eax
Packit Service 084de1
	mov	\$$PADLOCK_CHUNK,$chunk
Packit Service 084de1
	shl	\$4,%eax
Packit Service 084de1
	cmovz	$chunk,%rax
Packit Service 084de1
	cmp	%rax,$len
Packit Service 084de1
	cmova	%rax,$chunk		# don't let counter cross PADLOCK_CHUNK
Packit Service 084de1
	cmovbe	$len,$chunk
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___				if ($PADLOCK_PREFETCH{$mode});
Packit Service 084de1
	cmp	$chunk,$len
Packit Service 084de1
	ja	.L${mode}_loop
Packit Service 084de1
	mov	$inp,%rax		# check if prefetch crosses page
Packit Service 084de1
	cmp	%rsp,%rbp
Packit Service 084de1
	cmove	$out,%rax
Packit Service 084de1
	add	$len,%rax
Packit Service 084de1
	neg	%rax
Packit Service 084de1
	and	\$0xfff,%rax		# distance to page boundary
Packit Service 084de1
	cmp	\$$PADLOCK_PREFETCH{$mode},%rax
Packit Service 084de1
	mov	\$-$PADLOCK_PREFETCH{$mode},%rax
Packit Service 084de1
	cmovae	$chunk,%rax		# mask=distance
Packit Service 084de1
	and	%rax,$chunk
Packit Service 084de1
	jz	.L${mode}_unaligned_tail
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___;
Packit Service 084de1
	jmp	.L${mode}_loop
Packit Service 084de1
.align	16
Packit Service 084de1
.L${mode}_loop:
Packit Service 084de1
	cmp	$len,$chunk		# ctr32 artefact
Packit Service 084de1
	cmova	$len,$chunk		# ctr32 artefact
Packit Service 084de1
	mov	$out,%r8		# save parameters
Packit Service 084de1
	mov	$inp,%r9
Packit Service 084de1
	mov	$len,%r10
Packit Service 084de1
	mov	$chunk,$len
Packit Service 084de1
	mov	$chunk,%r11
Packit Service 084de1
	test	\$0x0f,$out		# out_misaligned
Packit Service 084de1
	cmovnz	%rsp,$out
Packit Service 084de1
	test	\$0x0f,$inp		# inp_misaligned
Packit Service 084de1
	jz	.L${mode}_inp_aligned
Packit Service 084de1
	shr	\$3,$len
Packit Service 084de1
	.byte	0xf3,0x48,0xa5		# rep movsq
Packit Service 084de1
	sub	$chunk,$out
Packit Service 084de1
	mov	$chunk,$len
Packit Service 084de1
	mov	$out,$inp
Packit Service 084de1
.L${mode}_inp_aligned:
Packit Service 084de1
	lea	-16($ctx),%rax		# ivp
Packit Service 084de1
	lea	16($ctx),%rbx		# key
Packit Service 084de1
	shr	\$4,$len
Packit Service 084de1
	.byte	0xf3,0x0f,0xa7,$opcode	# rep xcrypt*
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___				if ($mode !~ /ecb|ctr/);
Packit Service 084de1
	movdqa	(%rax),%xmm0
Packit Service 084de1
	movdqa	%xmm0,-16($ctx)		# copy [or refresh] iv
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___				if ($mode eq "ctr32");
Packit Service 084de1
	mov	-4($ctx),%eax		# pull 32-bit counter
Packit Service 084de1
	test	\$0xffff0000,%eax
Packit Service 084de1
	jnz	.L${mode}_no_carry
Packit Service 084de1
	bswap	%eax
Packit Service 084de1
	add	\$0x10000,%eax
Packit Service 084de1
	bswap	%eax
Packit Service 084de1
	mov	%eax,-4($ctx)
Packit Service 084de1
.L${mode}_no_carry:
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___;
Packit Service 084de1
	mov	%r8,$out		# restore parameters
Packit Service 084de1
	mov	%r11,$chunk
Packit Service 084de1
	test	\$0x0f,$out
Packit Service 084de1
	jz	.L${mode}_out_aligned
Packit Service 084de1
	mov	$chunk,$len
Packit Service 084de1
	lea	(%rsp),$inp
Packit Service 084de1
	shr	\$3,$len
Packit Service 084de1
	.byte	0xf3,0x48,0xa5		# rep movsq
Packit Service 084de1
	sub	$chunk,$out
Packit Service 084de1
.L${mode}_out_aligned:
Packit Service 084de1
	mov	%r9,$inp
Packit Service 084de1
	mov	%r10,$len
Packit Service 084de1
	add	$chunk,$out
Packit Service 084de1
	add	$chunk,$inp
Packit Service 084de1
	sub	$chunk,$len
Packit Service 084de1
	mov	\$$PADLOCK_CHUNK,$chunk
Packit Service 084de1
___
Packit Service 084de1
					if (!$PADLOCK_PREFETCH{$mode}) {
Packit Service 084de1
$code.=<<___;
Packit Service 084de1
	jnz	.L${mode}_loop
Packit Service 084de1
___
Packit Service 084de1
					} else {
Packit Service 084de1
$code.=<<___;
Packit Service 084de1
	jz	.L${mode}_break
Packit Service 084de1
	cmp	$chunk,$len
Packit Service 084de1
	jae	.L${mode}_loop
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___				if ($mode eq "ctr32");
Packit Service 084de1
	mov	$len,$chunk
Packit Service 084de1
	mov	$inp,%rax		# check if prefetch crosses page
Packit Service 084de1
	cmp	%rsp,%rbp
Packit Service 084de1
	cmove	$out,%rax
Packit Service 084de1
	add	$len,%rax
Packit Service 084de1
	neg	%rax
Packit Service 084de1
	and	\$0xfff,%rax		# distance to page boundary
Packit Service 084de1
	cmp	\$$PADLOCK_PREFETCH{$mode},%rax
Packit Service 084de1
	mov	\$-$PADLOCK_PREFETCH{$mode},%rax
Packit Service 084de1
	cmovae	$chunk,%rax
Packit Service 084de1
	and	%rax,$chunk
Packit Service 084de1
	jnz	.L${mode}_loop
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___;
Packit Service 084de1
.L${mode}_unaligned_tail:
Packit Service 084de1
	xor	%eax,%eax
Packit Service 084de1
	cmp	%rsp,%rbp
Packit Service 084de1
	cmove	$len,%rax
Packit Service 084de1
	mov	$out,%r8		# save parameters
Packit Service 084de1
	mov	$len,$chunk
Packit Service 084de1
	sub	%rax,%rsp		# alloca
Packit Service 084de1
	shr	\$3,$len
Packit Service 084de1
	lea	(%rsp),$out
Packit Service 084de1
	.byte	0xf3,0x48,0xa5		# rep movsq
Packit Service 084de1
	mov	%rsp,$inp
Packit Service 084de1
	mov	%r8, $out		# restore parameters
Packit Service 084de1
	mov	$chunk,$len
Packit Service 084de1
	jmp	.L${mode}_loop
Packit Service 084de1
.align	16
Packit Service 084de1
.L${mode}_break:
Packit Service 084de1
___
Packit Service 084de1
					}
Packit Service 084de1
$code.=<<___;
Packit Service 084de1
	cmp	%rbp,%rsp
Packit Service 084de1
	je	.L${mode}_done
Packit Service 084de1
Packit Service 084de1
	pxor	%xmm0,%xmm0
Packit Service 084de1
	lea	(%rsp),%rax
Packit Service 084de1
.L${mode}_bzero:
Packit Service 084de1
	movaps	%xmm0,(%rax)
Packit Service 084de1
	lea	16(%rax),%rax
Packit Service 084de1
	cmp	%rax,%rbp
Packit Service 084de1
	ja	.L${mode}_bzero
Packit Service 084de1
Packit Service 084de1
.L${mode}_done:
Packit Service 084de1
	lea	(%rbp),%rsp
Packit Service 084de1
	jmp	.L${mode}_exit
Packit Service 084de1
Packit Service 084de1
.align	16
Packit Service 084de1
.L${mode}_aligned:
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___				if ($mode eq "ctr32");
Packit Service 084de1
	mov	-4($ctx),%eax		# pull 32-bit counter
Packit Service 084de1
	bswap	%eax
Packit Service 084de1
	neg	%eax
Packit Service 084de1
	and	\$0xffff,%eax
Packit Service 084de1
	mov	\$`16*0x10000`,$chunk
Packit Service 084de1
	shl	\$4,%eax
Packit Service 084de1
	cmovz	$chunk,%rax
Packit Service 084de1
	cmp	%rax,$len
Packit Service 084de1
	cmova	%rax,$chunk		# don't let counter cross 2^16
Packit Service 084de1
	cmovbe	$len,$chunk
Packit Service 084de1
	jbe	.L${mode}_aligned_skip
Packit Service 084de1
Packit Service 084de1
.L${mode}_aligned_loop:
Packit Service 084de1
	mov	$len,%r10		# save parameters
Packit Service 084de1
	mov	$chunk,$len
Packit Service 084de1
	mov	$chunk,%r11
Packit Service 084de1
Packit Service 084de1
	lea	-16($ctx),%rax		# ivp
Packit Service 084de1
	lea	16($ctx),%rbx		# key
Packit Service 084de1
	shr	\$4,$len		# len/=AES_BLOCK_SIZE
Packit Service 084de1
	.byte	0xf3,0x0f,0xa7,$opcode	# rep xcrypt*
Packit Service 084de1
Packit Service 084de1
	mov	-4($ctx),%eax		# pull 32-bit counter
Packit Service 084de1
	bswap	%eax
Packit Service 084de1
	add	\$0x10000,%eax
Packit Service 084de1
	bswap	%eax
Packit Service 084de1
	mov	%eax,-4($ctx)
Packit Service 084de1
Packit Service 084de1
	mov	%r10,$len		# restore parameters
Packit Service 084de1
	sub	%r11,$len
Packit Service 084de1
	mov	\$`16*0x10000`,$chunk
Packit Service 084de1
	jz	.L${mode}_exit
Packit Service 084de1
	cmp	$chunk,$len
Packit Service 084de1
	jae	.L${mode}_aligned_loop
Packit Service 084de1
Packit Service 084de1
.L${mode}_aligned_skip:
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___				if ($PADLOCK_PREFETCH{$mode});
Packit Service 084de1
	lea	($inp,$len),%rbp
Packit Service 084de1
	neg	%rbp
Packit Service 084de1
	and	\$0xfff,%rbp		# distance to page boundary
Packit Service 084de1
	xor	%eax,%eax
Packit Service 084de1
	cmp	\$$PADLOCK_PREFETCH{$mode},%rbp
Packit Service 084de1
	mov	\$$PADLOCK_PREFETCH{$mode}-1,%rbp
Packit Service 084de1
	cmovae	%rax,%rbp
Packit Service 084de1
	and	$len,%rbp		# remainder
Packit Service 084de1
	sub	%rbp,$len
Packit Service 084de1
	jz	.L${mode}_aligned_tail
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___;
Packit Service 084de1
	lea	-16($ctx),%rax		# ivp
Packit Service 084de1
	lea	16($ctx),%rbx		# key
Packit Service 084de1
	shr	\$4,$len		# len/=AES_BLOCK_SIZE
Packit Service 084de1
	.byte	0xf3,0x0f,0xa7,$opcode	# rep xcrypt*
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___				if ($mode !~ /ecb|ctr/);
Packit Service 084de1
	movdqa	(%rax),%xmm0
Packit Service 084de1
	movdqa	%xmm0,-16($ctx)		# copy [or refresh] iv
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___				if ($PADLOCK_PREFETCH{$mode});
Packit Service 084de1
	test	%rbp,%rbp		# check remainder
Packit Service 084de1
	jz	.L${mode}_exit
Packit Service 084de1
Packit Service 084de1
.L${mode}_aligned_tail:
Packit Service 084de1
	mov	$out,%r8
Packit Service 084de1
	mov	%rbp,$chunk
Packit Service 084de1
	mov	%rbp,$len
Packit Service 084de1
	lea	(%rsp),%rbp
Packit Service 084de1
	sub	$len,%rsp
Packit Service 084de1
	shr	\$3,$len
Packit Service 084de1
	lea	(%rsp),$out
Packit Service 084de1
	.byte	0xf3,0x48,0xa5		# rep movsq
Packit Service 084de1
	lea	(%r8),$out
Packit Service 084de1
	lea	(%rsp),$inp
Packit Service 084de1
	mov	$chunk,$len
Packit Service 084de1
	jmp	.L${mode}_loop
Packit Service 084de1
___
Packit Service 084de1
$code.=<<___;
Packit Service 084de1
.L${mode}_exit:
Packit Service 084de1
	mov	\$1,%eax
Packit Service 084de1
	lea	8(%rsp),%rsp
Packit Service 084de1
.L${mode}_abort:
Packit Service 084de1
	pop	%rbx
Packit Service 084de1
	pop	%rbp
Packit Service 084de1
	ret
Packit Service 084de1
.size	padlock_${mode}_encrypt,.-padlock_${mode}_encrypt
Packit Service 084de1
___
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
&generate_mode("ecb",0xc8);
Packit Service 084de1
&generate_mode("cbc",0xd0);
Packit Service 084de1
&generate_mode("cfb",0xe0);
Packit Service 084de1
&generate_mode("ofb",0xe8);
Packit Service 084de1
&generate_mode("ctr32",0xd8);	# all 64-bit CPUs have working CTR...
Packit Service 084de1
Packit Service 084de1
$code.=<<___;
Packit Service 084de1
.asciz	"VIA Padlock x86_64 module, CRYPTOGAMS by <appro\@openssl.org>"
Packit Service 084de1
.align	16
Packit Service 084de1
.data
Packit Service 084de1
.align	8
Packit Service 084de1
.Lpadlock_saved_context:
Packit Service 084de1
	.quad	0
Packit Service 084de1
___
Packit Service 084de1
$code =~ s/\`([^\`]*)\`/eval($1)/gem;
Packit Service 084de1
Packit Service 084de1
print $code;
Packit Service 084de1
Packit Service 084de1
close STDOUT;