1e71b7053SJung-uk Kim#! /usr/bin/env perl
2640242a5SJung-uk Kim# Copyright 2011-2023 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim#
4*b077aed3SPierre Pronchery# Licensed under the Apache License 2.0 (the "License").  You may not use
5e71b7053SJung-uk Kim# this file except in compliance with the License.  You can obtain a copy
6e71b7053SJung-uk Kim# in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim# https://www.openssl.org/source/license.html
8e71b7053SJung-uk Kim
9e71b7053SJung-uk Kim
10e71b7053SJung-uk Kim# ====================================================================
11e71b7053SJung-uk Kim# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
12e71b7053SJung-uk Kim# project. The module is, however, dual licensed under OpenSSL and
13e71b7053SJung-uk Kim# CRYPTOGAMS licenses depending on where you obtain it. For further
14e71b7053SJung-uk Kim# details see http://www.openssl.org/~appro/cryptogams/.
15e71b7053SJung-uk Kim# ====================================================================
16e71b7053SJung-uk Kim
17e71b7053SJung-uk Kim# September 2011
18e71b7053SJung-uk Kim#
19e71b7053SJung-uk Kim# Assembler helpers for Padlock engine. See even e_padlock-x86.pl for
20e71b7053SJung-uk Kim# details.
21e71b7053SJung-uk Kim
22*b077aed3SPierre Pronchery# $output is the last argument if it looks like a file (it has an extension)
23*b077aed3SPierre Pronchery# $flavour is the first argument if it doesn't look like a file
24*b077aed3SPierre Pronchery$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
25*b077aed3SPierre Pronchery$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
26e71b7053SJung-uk Kim
27e71b7053SJung-uk Kim$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
28e71b7053SJung-uk Kim
29e71b7053SJung-uk Kim$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
30e71b7053SJung-uk Kim( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
31e71b7053SJung-uk Kim( $xlate="${dir}../../crypto/perlasm/x86_64-xlate.pl" and -f $xlate) or
32e71b7053SJung-uk Kimdie "can't locate x86_64-xlate.pl";
33e71b7053SJung-uk Kim
34*b077aed3SPierre Proncheryopen OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
35*b077aed3SPierre Pronchery     or die "can't call $xlate: $!";
36e71b7053SJung-uk Kim*STDOUT=*OUT;
37e71b7053SJung-uk Kim
38e71b7053SJung-uk Kim$code=".text\n";
39e71b7053SJung-uk Kim
40e71b7053SJung-uk Kim%PADLOCK_PREFETCH=(ecb=>128, cbc=>64, ctr32=>32);	# prefetch errata
41e71b7053SJung-uk Kim$PADLOCK_CHUNK=512;	# Must be a power of 2 between 32 and 2^20
42e71b7053SJung-uk Kim
43e71b7053SJung-uk Kim$ctx="%rdx";
44e71b7053SJung-uk Kim$out="%rdi";
45e71b7053SJung-uk Kim$inp="%rsi";
46e71b7053SJung-uk Kim$len="%rcx";
47e71b7053SJung-uk Kim$chunk="%rbx";
48e71b7053SJung-uk Kim
49e71b7053SJung-uk Kim($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order
50e71b7053SJung-uk Kim                                 ("%rdi","%rsi","%rdx","%rcx"); # Unix order
51e71b7053SJung-uk Kim
52e71b7053SJung-uk Kim$code.=<<___;
53e71b7053SJung-uk Kim.globl	padlock_capability
54e71b7053SJung-uk Kim.type	padlock_capability,\@abi-omnipotent
55e71b7053SJung-uk Kim.align	16
56e71b7053SJung-uk Kimpadlock_capability:
57e71b7053SJung-uk Kim	mov	%rbx,%r8
58e71b7053SJung-uk Kim	xor	%eax,%eax
59e71b7053SJung-uk Kim	cpuid
60e71b7053SJung-uk Kim	xor	%eax,%eax
61e71b7053SJung-uk Kim	cmp	\$`"0x".unpack("H*",'tneC')`,%ebx
62e71b7053SJung-uk Kim	jne	.Lzhaoxin
63e71b7053SJung-uk Kim	cmp	\$`"0x".unpack("H*",'Hrua')`,%edx
64e71b7053SJung-uk Kim	jne	.Lnoluck
65e71b7053SJung-uk Kim	cmp	\$`"0x".unpack("H*",'slua')`,%ecx
66e71b7053SJung-uk Kim	jne	.Lnoluck
67e71b7053SJung-uk Kim	jmp	.LzhaoxinEnd
68e71b7053SJung-uk Kim.Lzhaoxin:
69e71b7053SJung-uk Kim	cmp	\$`"0x".unpack("H*",'hS  ')`,%ebx
70e71b7053SJung-uk Kim	jne	.Lnoluck
71e71b7053SJung-uk Kim	cmp	\$`"0x".unpack("H*",'hgna')`,%edx
72e71b7053SJung-uk Kim	jne	.Lnoluck
73e71b7053SJung-uk Kim	cmp	\$`"0x".unpack("H*",'  ia')`,%ecx
74e71b7053SJung-uk Kim	jne	.Lnoluck
75e71b7053SJung-uk Kim.LzhaoxinEnd:
76e71b7053SJung-uk Kim	mov	\$0xC0000000,%eax
77e71b7053SJung-uk Kim	cpuid
78e71b7053SJung-uk Kim	mov	%eax,%edx
79e71b7053SJung-uk Kim	xor	%eax,%eax
80e71b7053SJung-uk Kim	cmp	\$0xC0000001,%edx
81e71b7053SJung-uk Kim	jb	.Lnoluck
82e71b7053SJung-uk Kim	mov	\$0xC0000001,%eax
83e71b7053SJung-uk Kim	cpuid
84e71b7053SJung-uk Kim	mov	%edx,%eax
85e71b7053SJung-uk Kim	and	\$0xffffffef,%eax
86e71b7053SJung-uk Kim	or	\$0x10,%eax		# set Nano bit#4
87e71b7053SJung-uk Kim.Lnoluck:
88e71b7053SJung-uk Kim	mov	%r8,%rbx
89e71b7053SJung-uk Kim	ret
90e71b7053SJung-uk Kim.size	padlock_capability,.-padlock_capability
91e71b7053SJung-uk Kim
92e71b7053SJung-uk Kim.globl	padlock_key_bswap
93e71b7053SJung-uk Kim.type	padlock_key_bswap,\@abi-omnipotent,0
94e71b7053SJung-uk Kim.align	16
95e71b7053SJung-uk Kimpadlock_key_bswap:
96e71b7053SJung-uk Kim	mov	240($arg1),%edx
97640242a5SJung-uk Kim	inc	%edx
98640242a5SJung-uk Kim	shl	\$2,%edx
99e71b7053SJung-uk Kim.Lbswap_loop:
100e71b7053SJung-uk Kim	mov	($arg1),%eax
101e71b7053SJung-uk Kim	bswap	%eax
102e71b7053SJung-uk Kim	mov	%eax,($arg1)
103e71b7053SJung-uk Kim	lea	4($arg1),$arg1
104e71b7053SJung-uk Kim	sub	\$1,%edx
105e71b7053SJung-uk Kim	jnz	.Lbswap_loop
106e71b7053SJung-uk Kim	ret
107e71b7053SJung-uk Kim.size	padlock_key_bswap,.-padlock_key_bswap
108e71b7053SJung-uk Kim
109e71b7053SJung-uk Kim.globl	padlock_verify_context
110e71b7053SJung-uk Kim.type	padlock_verify_context,\@abi-omnipotent
111e71b7053SJung-uk Kim.align	16
112e71b7053SJung-uk Kimpadlock_verify_context:
113e71b7053SJung-uk Kim	mov	$arg1,$ctx
114e71b7053SJung-uk Kim	pushf
115e71b7053SJung-uk Kim	lea	.Lpadlock_saved_context(%rip),%rax
116e71b7053SJung-uk Kim	call	_padlock_verify_ctx
117e71b7053SJung-uk Kim	lea	8(%rsp),%rsp
118e71b7053SJung-uk Kim	ret
119e71b7053SJung-uk Kim.size	padlock_verify_context,.-padlock_verify_context
120e71b7053SJung-uk Kim
121e71b7053SJung-uk Kim.type	_padlock_verify_ctx,\@abi-omnipotent
122e71b7053SJung-uk Kim.align	16
123e71b7053SJung-uk Kim_padlock_verify_ctx:
124e71b7053SJung-uk Kim	mov	8(%rsp),%r8
125e71b7053SJung-uk Kim	bt	\$30,%r8
126e71b7053SJung-uk Kim	jnc	.Lverified
127e71b7053SJung-uk Kim	cmp	(%rax),$ctx
128e71b7053SJung-uk Kim	je	.Lverified
129e71b7053SJung-uk Kim	pushf
130e71b7053SJung-uk Kim	popf
131e71b7053SJung-uk Kim.Lverified:
132e71b7053SJung-uk Kim	mov	$ctx,(%rax)
133e71b7053SJung-uk Kim	ret
134e71b7053SJung-uk Kim.size	_padlock_verify_ctx,.-_padlock_verify_ctx
135e71b7053SJung-uk Kim
136e71b7053SJung-uk Kim.globl	padlock_reload_key
137e71b7053SJung-uk Kim.type	padlock_reload_key,\@abi-omnipotent
138e71b7053SJung-uk Kim.align	16
139e71b7053SJung-uk Kimpadlock_reload_key:
140e71b7053SJung-uk Kim	pushf
141e71b7053SJung-uk Kim	popf
142e71b7053SJung-uk Kim	ret
143e71b7053SJung-uk Kim.size	padlock_reload_key,.-padlock_reload_key
144e71b7053SJung-uk Kim
145e71b7053SJung-uk Kim.globl	padlock_aes_block
146e71b7053SJung-uk Kim.type	padlock_aes_block,\@function,3
147e71b7053SJung-uk Kim.align	16
148e71b7053SJung-uk Kimpadlock_aes_block:
149e71b7053SJung-uk Kim	mov	%rbx,%r8
150e71b7053SJung-uk Kim	mov	\$1,$len
151e71b7053SJung-uk Kim	lea	32($ctx),%rbx		# key
152e71b7053SJung-uk Kim	lea	16($ctx),$ctx		# control word
153e71b7053SJung-uk Kim	.byte	0xf3,0x0f,0xa7,0xc8	# rep xcryptecb
154e71b7053SJung-uk Kim	mov	%r8,%rbx
155e71b7053SJung-uk Kim	ret
156e71b7053SJung-uk Kim.size	padlock_aes_block,.-padlock_aes_block
157e71b7053SJung-uk Kim
158e71b7053SJung-uk Kim.globl	padlock_xstore
159e71b7053SJung-uk Kim.type	padlock_xstore,\@function,2
160e71b7053SJung-uk Kim.align	16
161e71b7053SJung-uk Kimpadlock_xstore:
162e71b7053SJung-uk Kim	mov	%esi,%edx
163e71b7053SJung-uk Kim	.byte	0x0f,0xa7,0xc0		# xstore
164e71b7053SJung-uk Kim	ret
165e71b7053SJung-uk Kim.size	padlock_xstore,.-padlock_xstore
166e71b7053SJung-uk Kim
167e71b7053SJung-uk Kim.globl	padlock_sha1_oneshot
168e71b7053SJung-uk Kim.type	padlock_sha1_oneshot,\@function,3
169e71b7053SJung-uk Kim.align	16
170e71b7053SJung-uk Kimpadlock_sha1_oneshot:
171e71b7053SJung-uk Kim	mov	%rdx,%rcx
172e71b7053SJung-uk Kim	mov	%rdi,%rdx		# put aside %rdi
173e71b7053SJung-uk Kim	movups	(%rdi),%xmm0		# copy-in context
174e71b7053SJung-uk Kim	sub	\$128+8,%rsp
175e71b7053SJung-uk Kim	mov	16(%rdi),%eax
176e71b7053SJung-uk Kim	movaps	%xmm0,(%rsp)
177e71b7053SJung-uk Kim	mov	%rsp,%rdi
178e71b7053SJung-uk Kim	mov	%eax,16(%rsp)
179e71b7053SJung-uk Kim	xor	%rax,%rax
180e71b7053SJung-uk Kim	.byte	0xf3,0x0f,0xa6,0xc8	# rep xsha1
181e71b7053SJung-uk Kim	movaps	(%rsp),%xmm0
182e71b7053SJung-uk Kim	mov	16(%rsp),%eax
183e71b7053SJung-uk Kim	add	\$128+8,%rsp
184e71b7053SJung-uk Kim	movups	%xmm0,(%rdx)		# copy-out context
185e71b7053SJung-uk Kim	mov	%eax,16(%rdx)
186e71b7053SJung-uk Kim	ret
187e71b7053SJung-uk Kim.size	padlock_sha1_oneshot,.-padlock_sha1_oneshot
188e71b7053SJung-uk Kim
189e71b7053SJung-uk Kim.globl	padlock_sha1_blocks
190e71b7053SJung-uk Kim.type	padlock_sha1_blocks,\@function,3
191e71b7053SJung-uk Kim.align	16
192e71b7053SJung-uk Kimpadlock_sha1_blocks:
193e71b7053SJung-uk Kim	mov	%rdx,%rcx
194e71b7053SJung-uk Kim	mov	%rdi,%rdx		# put aside %rdi
195e71b7053SJung-uk Kim	movups	(%rdi),%xmm0		# copy-in context
196e71b7053SJung-uk Kim	sub	\$128+8,%rsp
197e71b7053SJung-uk Kim	mov	16(%rdi),%eax
198e71b7053SJung-uk Kim	movaps	%xmm0,(%rsp)
199e71b7053SJung-uk Kim	mov	%rsp,%rdi
200e71b7053SJung-uk Kim	mov	%eax,16(%rsp)
201e71b7053SJung-uk Kim	mov	\$-1,%rax
202e71b7053SJung-uk Kim	.byte	0xf3,0x0f,0xa6,0xc8	# rep xsha1
203e71b7053SJung-uk Kim	movaps	(%rsp),%xmm0
204e71b7053SJung-uk Kim	mov	16(%rsp),%eax
205e71b7053SJung-uk Kim	add	\$128+8,%rsp
206e71b7053SJung-uk Kim	movups	%xmm0,(%rdx)		# copy-out context
207e71b7053SJung-uk Kim	mov	%eax,16(%rdx)
208e71b7053SJung-uk Kim	ret
209e71b7053SJung-uk Kim.size	padlock_sha1_blocks,.-padlock_sha1_blocks
210e71b7053SJung-uk Kim
211e71b7053SJung-uk Kim.globl	padlock_sha256_oneshot
212e71b7053SJung-uk Kim.type	padlock_sha256_oneshot,\@function,3
213e71b7053SJung-uk Kim.align	16
214e71b7053SJung-uk Kimpadlock_sha256_oneshot:
215e71b7053SJung-uk Kim	mov	%rdx,%rcx
216e71b7053SJung-uk Kim	mov	%rdi,%rdx		# put aside %rdi
217e71b7053SJung-uk Kim	movups	(%rdi),%xmm0		# copy-in context
218e71b7053SJung-uk Kim	sub	\$128+8,%rsp
219e71b7053SJung-uk Kim	movups	16(%rdi),%xmm1
220e71b7053SJung-uk Kim	movaps	%xmm0,(%rsp)
221e71b7053SJung-uk Kim	mov	%rsp,%rdi
222e71b7053SJung-uk Kim	movaps	%xmm1,16(%rsp)
223e71b7053SJung-uk Kim	xor	%rax,%rax
224e71b7053SJung-uk Kim	.byte	0xf3,0x0f,0xa6,0xd0	# rep xsha256
225e71b7053SJung-uk Kim	movaps	(%rsp),%xmm0
226e71b7053SJung-uk Kim	movaps	16(%rsp),%xmm1
227e71b7053SJung-uk Kim	add	\$128+8,%rsp
228e71b7053SJung-uk Kim	movups	%xmm0,(%rdx)		# copy-out context
229e71b7053SJung-uk Kim	movups	%xmm1,16(%rdx)
230e71b7053SJung-uk Kim	ret
231e71b7053SJung-uk Kim.size	padlock_sha256_oneshot,.-padlock_sha256_oneshot
232e71b7053SJung-uk Kim
233e71b7053SJung-uk Kim.globl	padlock_sha256_blocks
234e71b7053SJung-uk Kim.type	padlock_sha256_blocks,\@function,3
235e71b7053SJung-uk Kim.align	16
236e71b7053SJung-uk Kimpadlock_sha256_blocks:
237e71b7053SJung-uk Kim	mov	%rdx,%rcx
238e71b7053SJung-uk Kim	mov	%rdi,%rdx		# put aside %rdi
239e71b7053SJung-uk Kim	movups	(%rdi),%xmm0		# copy-in context
240e71b7053SJung-uk Kim	sub	\$128+8,%rsp
241e71b7053SJung-uk Kim	movups	16(%rdi),%xmm1
242e71b7053SJung-uk Kim	movaps	%xmm0,(%rsp)
243e71b7053SJung-uk Kim	mov	%rsp,%rdi
244e71b7053SJung-uk Kim	movaps	%xmm1,16(%rsp)
245e71b7053SJung-uk Kim	mov	\$-1,%rax
246e71b7053SJung-uk Kim	.byte	0xf3,0x0f,0xa6,0xd0	# rep xsha256
247e71b7053SJung-uk Kim	movaps	(%rsp),%xmm0
248e71b7053SJung-uk Kim	movaps	16(%rsp),%xmm1
249e71b7053SJung-uk Kim	add	\$128+8,%rsp
250e71b7053SJung-uk Kim	movups	%xmm0,(%rdx)		# copy-out context
251e71b7053SJung-uk Kim	movups	%xmm1,16(%rdx)
252e71b7053SJung-uk Kim	ret
253e71b7053SJung-uk Kim.size	padlock_sha256_blocks,.-padlock_sha256_blocks
254e71b7053SJung-uk Kim
255e71b7053SJung-uk Kim.globl	padlock_sha512_blocks
256e71b7053SJung-uk Kim.type	padlock_sha512_blocks,\@function,3
257e71b7053SJung-uk Kim.align	16
258e71b7053SJung-uk Kimpadlock_sha512_blocks:
259e71b7053SJung-uk Kim	mov	%rdx,%rcx
260e71b7053SJung-uk Kim	mov	%rdi,%rdx		# put aside %rdi
261e71b7053SJung-uk Kim	movups	(%rdi),%xmm0		# copy-in context
262e71b7053SJung-uk Kim	sub	\$128+8,%rsp
263e71b7053SJung-uk Kim	movups	16(%rdi),%xmm1
264e71b7053SJung-uk Kim	movups	32(%rdi),%xmm2
265e71b7053SJung-uk Kim	movups	48(%rdi),%xmm3
266e71b7053SJung-uk Kim	movaps	%xmm0,(%rsp)
267e71b7053SJung-uk Kim	mov	%rsp,%rdi
268e71b7053SJung-uk Kim	movaps	%xmm1,16(%rsp)
269e71b7053SJung-uk Kim	movaps	%xmm2,32(%rsp)
270e71b7053SJung-uk Kim	movaps	%xmm3,48(%rsp)
271e71b7053SJung-uk Kim	.byte	0xf3,0x0f,0xa6,0xe0	# rep xha512
272e71b7053SJung-uk Kim	movaps	(%rsp),%xmm0
273e71b7053SJung-uk Kim	movaps	16(%rsp),%xmm1
274e71b7053SJung-uk Kim	movaps	32(%rsp),%xmm2
275e71b7053SJung-uk Kim	movaps	48(%rsp),%xmm3
276e71b7053SJung-uk Kim	add	\$128+8,%rsp
277e71b7053SJung-uk Kim	movups	%xmm0,(%rdx)		# copy-out context
278e71b7053SJung-uk Kim	movups	%xmm1,16(%rdx)
279e71b7053SJung-uk Kim	movups	%xmm2,32(%rdx)
280e71b7053SJung-uk Kim	movups	%xmm3,48(%rdx)
281e71b7053SJung-uk Kim	ret
282e71b7053SJung-uk Kim.size	padlock_sha512_blocks,.-padlock_sha512_blocks
283e71b7053SJung-uk Kim___
284e71b7053SJung-uk Kim
285e71b7053SJung-uk Kimsub generate_mode {
286e71b7053SJung-uk Kimmy ($mode,$opcode) = @_;
287e71b7053SJung-uk Kim# int padlock_$mode_encrypt(void *out, const void *inp,
288e71b7053SJung-uk Kim#		struct padlock_cipher_data *ctx, size_t len);
289e71b7053SJung-uk Kim$code.=<<___;
290e71b7053SJung-uk Kim.globl	padlock_${mode}_encrypt
291e71b7053SJung-uk Kim.type	padlock_${mode}_encrypt,\@function,4
292e71b7053SJung-uk Kim.align	16
293e71b7053SJung-uk Kimpadlock_${mode}_encrypt:
294e71b7053SJung-uk Kim	push	%rbp
295e71b7053SJung-uk Kim	push	%rbx
296e71b7053SJung-uk Kim
297e71b7053SJung-uk Kim	xor	%eax,%eax
298e71b7053SJung-uk Kim	test	\$15,$ctx
299e71b7053SJung-uk Kim	jnz	.L${mode}_abort
300e71b7053SJung-uk Kim	test	\$15,$len
301e71b7053SJung-uk Kim	jnz	.L${mode}_abort
302e71b7053SJung-uk Kim	lea	.Lpadlock_saved_context(%rip),%rax
303e71b7053SJung-uk Kim	pushf
304e71b7053SJung-uk Kim	cld
305e71b7053SJung-uk Kim	call	_padlock_verify_ctx
306e71b7053SJung-uk Kim	lea	16($ctx),$ctx		# control word
307e71b7053SJung-uk Kim	xor	%eax,%eax
308e71b7053SJung-uk Kim	xor	%ebx,%ebx
309e71b7053SJung-uk Kim	testl	\$`1<<5`,($ctx)		# align bit in control word
310e71b7053SJung-uk Kim	jnz	.L${mode}_aligned
311e71b7053SJung-uk Kim	test	\$0x0f,$out
312e71b7053SJung-uk Kim	setz	%al			# !out_misaligned
313e71b7053SJung-uk Kim	test	\$0x0f,$inp
314e71b7053SJung-uk Kim	setz	%bl			# !inp_misaligned
315e71b7053SJung-uk Kim	test	%ebx,%eax
316e71b7053SJung-uk Kim	jnz	.L${mode}_aligned
317e71b7053SJung-uk Kim	neg	%rax
318e71b7053SJung-uk Kim	mov	\$$PADLOCK_CHUNK,$chunk
319e71b7053SJung-uk Kim	not	%rax			# out_misaligned?-1:0
320e71b7053SJung-uk Kim	lea	(%rsp),%rbp
321e71b7053SJung-uk Kim	cmp	$chunk,$len
322e71b7053SJung-uk Kim	cmovc	$len,$chunk		# chunk=len>PADLOCK_CHUNK?PADLOCK_CHUNK:len
323e71b7053SJung-uk Kim	and	$chunk,%rax		# out_misaligned?chunk:0
324e71b7053SJung-uk Kim	mov	$len,$chunk
325e71b7053SJung-uk Kim	neg	%rax
326e71b7053SJung-uk Kim	and	\$$PADLOCK_CHUNK-1,$chunk	# chunk%=PADLOCK_CHUNK
327e71b7053SJung-uk Kim	lea	(%rax,%rbp),%rsp
328e71b7053SJung-uk Kim	mov	\$$PADLOCK_CHUNK,%rax
329e71b7053SJung-uk Kim	cmovz	%rax,$chunk			# chunk=chunk?:PADLOCK_CHUNK
330e71b7053SJung-uk Kim___
331e71b7053SJung-uk Kim$code.=<<___				if ($mode eq "ctr32");
332e71b7053SJung-uk Kim.L${mode}_reenter:
333e71b7053SJung-uk Kim	mov	-4($ctx),%eax		# pull 32-bit counter
334e71b7053SJung-uk Kim	bswap	%eax
335e71b7053SJung-uk Kim	neg	%eax
336e71b7053SJung-uk Kim	and	\$`$PADLOCK_CHUNK/16-1`,%eax
337e71b7053SJung-uk Kim	mov	\$$PADLOCK_CHUNK,$chunk
338e71b7053SJung-uk Kim	shl	\$4,%eax
339e71b7053SJung-uk Kim	cmovz	$chunk,%rax
340e71b7053SJung-uk Kim	cmp	%rax,$len
341e71b7053SJung-uk Kim	cmova	%rax,$chunk		# don't let counter cross PADLOCK_CHUNK
342e71b7053SJung-uk Kim	cmovbe	$len,$chunk
343e71b7053SJung-uk Kim___
344e71b7053SJung-uk Kim$code.=<<___				if ($PADLOCK_PREFETCH{$mode});
345e71b7053SJung-uk Kim	cmp	$chunk,$len
346e71b7053SJung-uk Kim	ja	.L${mode}_loop
347e71b7053SJung-uk Kim	mov	$inp,%rax		# check if prefetch crosses page
348e71b7053SJung-uk Kim	cmp	%rsp,%rbp
349e71b7053SJung-uk Kim	cmove	$out,%rax
350e71b7053SJung-uk Kim	add	$len,%rax
351e71b7053SJung-uk Kim	neg	%rax
352e71b7053SJung-uk Kim	and	\$0xfff,%rax		# distance to page boundary
353e71b7053SJung-uk Kim	cmp	\$$PADLOCK_PREFETCH{$mode},%rax
354e71b7053SJung-uk Kim	mov	\$-$PADLOCK_PREFETCH{$mode},%rax
355e71b7053SJung-uk Kim	cmovae	$chunk,%rax		# mask=distance<prefetch?-prefetch:-1
356e71b7053SJung-uk Kim	and	%rax,$chunk
357e71b7053SJung-uk Kim	jz	.L${mode}_unaligned_tail
358e71b7053SJung-uk Kim___
359e71b7053SJung-uk Kim$code.=<<___;
360e71b7053SJung-uk Kim	jmp	.L${mode}_loop
361e71b7053SJung-uk Kim.align	16
362e71b7053SJung-uk Kim.L${mode}_loop:
363e71b7053SJung-uk Kim	cmp	$len,$chunk		# ctr32 artefact
364e71b7053SJung-uk Kim	cmova	$len,$chunk		# ctr32 artefact
365e71b7053SJung-uk Kim	mov	$out,%r8		# save parameters
366e71b7053SJung-uk Kim	mov	$inp,%r9
367e71b7053SJung-uk Kim	mov	$len,%r10
368e71b7053SJung-uk Kim	mov	$chunk,$len
369e71b7053SJung-uk Kim	mov	$chunk,%r11
370e71b7053SJung-uk Kim	test	\$0x0f,$out		# out_misaligned
371e71b7053SJung-uk Kim	cmovnz	%rsp,$out
372e71b7053SJung-uk Kim	test	\$0x0f,$inp		# inp_misaligned
373e71b7053SJung-uk Kim	jz	.L${mode}_inp_aligned
374e71b7053SJung-uk Kim	shr	\$3,$len
375e71b7053SJung-uk Kim	.byte	0xf3,0x48,0xa5		# rep movsq
376e71b7053SJung-uk Kim	sub	$chunk,$out
377e71b7053SJung-uk Kim	mov	$chunk,$len
378e71b7053SJung-uk Kim	mov	$out,$inp
379e71b7053SJung-uk Kim.L${mode}_inp_aligned:
380e71b7053SJung-uk Kim	lea	-16($ctx),%rax		# ivp
381e71b7053SJung-uk Kim	lea	16($ctx),%rbx		# key
382e71b7053SJung-uk Kim	shr	\$4,$len
383e71b7053SJung-uk Kim	.byte	0xf3,0x0f,0xa7,$opcode	# rep xcrypt*
384e71b7053SJung-uk Kim___
385e71b7053SJung-uk Kim$code.=<<___				if ($mode !~ /ecb|ctr/);
386e71b7053SJung-uk Kim	movdqa	(%rax),%xmm0
387e71b7053SJung-uk Kim	movdqa	%xmm0,-16($ctx)		# copy [or refresh] iv
388e71b7053SJung-uk Kim___
389e71b7053SJung-uk Kim$code.=<<___				if ($mode eq "ctr32");
390e71b7053SJung-uk Kim	mov	-4($ctx),%eax		# pull 32-bit counter
391e71b7053SJung-uk Kim	test	\$0xffff0000,%eax
392e71b7053SJung-uk Kim	jnz	.L${mode}_no_carry
393e71b7053SJung-uk Kim	bswap	%eax
394e71b7053SJung-uk Kim	add	\$0x10000,%eax
395e71b7053SJung-uk Kim	bswap	%eax
396e71b7053SJung-uk Kim	mov	%eax,-4($ctx)
397e71b7053SJung-uk Kim.L${mode}_no_carry:
398e71b7053SJung-uk Kim___
399e71b7053SJung-uk Kim$code.=<<___;
400e71b7053SJung-uk Kim	mov	%r8,$out		# restore parameters
401e71b7053SJung-uk Kim	mov	%r11,$chunk
402e71b7053SJung-uk Kim	test	\$0x0f,$out
403e71b7053SJung-uk Kim	jz	.L${mode}_out_aligned
404e71b7053SJung-uk Kim	mov	$chunk,$len
405e71b7053SJung-uk Kim	lea	(%rsp),$inp
406e71b7053SJung-uk Kim	shr	\$3,$len
407e71b7053SJung-uk Kim	.byte	0xf3,0x48,0xa5		# rep movsq
408e71b7053SJung-uk Kim	sub	$chunk,$out
409e71b7053SJung-uk Kim.L${mode}_out_aligned:
410e71b7053SJung-uk Kim	mov	%r9,$inp
411e71b7053SJung-uk Kim	mov	%r10,$len
412e71b7053SJung-uk Kim	add	$chunk,$out
413e71b7053SJung-uk Kim	add	$chunk,$inp
414e71b7053SJung-uk Kim	sub	$chunk,$len
415e71b7053SJung-uk Kim	mov	\$$PADLOCK_CHUNK,$chunk
416e71b7053SJung-uk Kim___
417e71b7053SJung-uk Kim					if (!$PADLOCK_PREFETCH{$mode}) {
418e71b7053SJung-uk Kim$code.=<<___;
419e71b7053SJung-uk Kim	jnz	.L${mode}_loop
420e71b7053SJung-uk Kim___
421e71b7053SJung-uk Kim					} else {
422e71b7053SJung-uk Kim$code.=<<___;
423e71b7053SJung-uk Kim	jz	.L${mode}_break
424e71b7053SJung-uk Kim	cmp	$chunk,$len
425e71b7053SJung-uk Kim	jae	.L${mode}_loop
426e71b7053SJung-uk Kim___
427e71b7053SJung-uk Kim$code.=<<___				if ($mode eq "ctr32");
428e71b7053SJung-uk Kim	mov	$len,$chunk
429e71b7053SJung-uk Kim	mov	$inp,%rax		# check if prefetch crosses page
430e71b7053SJung-uk Kim	cmp	%rsp,%rbp
431e71b7053SJung-uk Kim	cmove	$out,%rax
432e71b7053SJung-uk Kim	add	$len,%rax
433e71b7053SJung-uk Kim	neg	%rax
434e71b7053SJung-uk Kim	and	\$0xfff,%rax		# distance to page boundary
435e71b7053SJung-uk Kim	cmp	\$$PADLOCK_PREFETCH{$mode},%rax
436e71b7053SJung-uk Kim	mov	\$-$PADLOCK_PREFETCH{$mode},%rax
437e71b7053SJung-uk Kim	cmovae	$chunk,%rax
438e71b7053SJung-uk Kim	and	%rax,$chunk
439e71b7053SJung-uk Kim	jnz	.L${mode}_loop
440e71b7053SJung-uk Kim___
441e71b7053SJung-uk Kim$code.=<<___;
442e71b7053SJung-uk Kim.L${mode}_unaligned_tail:
443e71b7053SJung-uk Kim	xor	%eax,%eax
444e71b7053SJung-uk Kim	cmp	%rsp,%rbp
445e71b7053SJung-uk Kim	cmove	$len,%rax
446e71b7053SJung-uk Kim	mov	$out,%r8		# save parameters
447e71b7053SJung-uk Kim	mov	$len,$chunk
448e71b7053SJung-uk Kim	sub	%rax,%rsp		# alloca
449e71b7053SJung-uk Kim	shr	\$3,$len
450e71b7053SJung-uk Kim	lea	(%rsp),$out
451e71b7053SJung-uk Kim	.byte	0xf3,0x48,0xa5		# rep movsq
452e71b7053SJung-uk Kim	mov	%rsp,$inp
453e71b7053SJung-uk Kim	mov	%r8, $out		# restore parameters
454e71b7053SJung-uk Kim	mov	$chunk,$len
455e71b7053SJung-uk Kim	jmp	.L${mode}_loop
456e71b7053SJung-uk Kim.align	16
457e71b7053SJung-uk Kim.L${mode}_break:
458e71b7053SJung-uk Kim___
459e71b7053SJung-uk Kim					}
460e71b7053SJung-uk Kim$code.=<<___;
461e71b7053SJung-uk Kim	cmp	%rbp,%rsp
462e71b7053SJung-uk Kim	je	.L${mode}_done
463e71b7053SJung-uk Kim
464e71b7053SJung-uk Kim	pxor	%xmm0,%xmm0
465e71b7053SJung-uk Kim	lea	(%rsp),%rax
466e71b7053SJung-uk Kim.L${mode}_bzero:
467e71b7053SJung-uk Kim	movaps	%xmm0,(%rax)
468e71b7053SJung-uk Kim	lea	16(%rax),%rax
469e71b7053SJung-uk Kim	cmp	%rax,%rbp
470e71b7053SJung-uk Kim	ja	.L${mode}_bzero
471e71b7053SJung-uk Kim
472e71b7053SJung-uk Kim.L${mode}_done:
473e71b7053SJung-uk Kim	lea	(%rbp),%rsp
474e71b7053SJung-uk Kim	jmp	.L${mode}_exit
475e71b7053SJung-uk Kim
476e71b7053SJung-uk Kim.align	16
477e71b7053SJung-uk Kim.L${mode}_aligned:
478e71b7053SJung-uk Kim___
479e71b7053SJung-uk Kim$code.=<<___				if ($mode eq "ctr32");
480e71b7053SJung-uk Kim	mov	-4($ctx),%eax		# pull 32-bit counter
481e71b7053SJung-uk Kim	bswap	%eax
482e71b7053SJung-uk Kim	neg	%eax
483e71b7053SJung-uk Kim	and	\$0xffff,%eax
484e71b7053SJung-uk Kim	mov	\$`16*0x10000`,$chunk
485e71b7053SJung-uk Kim	shl	\$4,%eax
486e71b7053SJung-uk Kim	cmovz	$chunk,%rax
487e71b7053SJung-uk Kim	cmp	%rax,$len
488e71b7053SJung-uk Kim	cmova	%rax,$chunk		# don't let counter cross 2^16
489e71b7053SJung-uk Kim	cmovbe	$len,$chunk
490e71b7053SJung-uk Kim	jbe	.L${mode}_aligned_skip
491e71b7053SJung-uk Kim
492e71b7053SJung-uk Kim.L${mode}_aligned_loop:
493e71b7053SJung-uk Kim	mov	$len,%r10		# save parameters
494e71b7053SJung-uk Kim	mov	$chunk,$len
495e71b7053SJung-uk Kim	mov	$chunk,%r11
496e71b7053SJung-uk Kim
497e71b7053SJung-uk Kim	lea	-16($ctx),%rax		# ivp
498e71b7053SJung-uk Kim	lea	16($ctx),%rbx		# key
499e71b7053SJung-uk Kim	shr	\$4,$len		# len/=AES_BLOCK_SIZE
500e71b7053SJung-uk Kim	.byte	0xf3,0x0f,0xa7,$opcode	# rep xcrypt*
501e71b7053SJung-uk Kim
502e71b7053SJung-uk Kim	mov	-4($ctx),%eax		# pull 32-bit counter
503e71b7053SJung-uk Kim	bswap	%eax
504e71b7053SJung-uk Kim	add	\$0x10000,%eax
505e71b7053SJung-uk Kim	bswap	%eax
506e71b7053SJung-uk Kim	mov	%eax,-4($ctx)
507e71b7053SJung-uk Kim
508e71b7053SJung-uk Kim	mov	%r10,$len		# restore parameters
509e71b7053SJung-uk Kim	sub	%r11,$len
510e71b7053SJung-uk Kim	mov	\$`16*0x10000`,$chunk
511e71b7053SJung-uk Kim	jz	.L${mode}_exit
512e71b7053SJung-uk Kim	cmp	$chunk,$len
513e71b7053SJung-uk Kim	jae	.L${mode}_aligned_loop
514e71b7053SJung-uk Kim
515e71b7053SJung-uk Kim.L${mode}_aligned_skip:
516e71b7053SJung-uk Kim___
517e71b7053SJung-uk Kim$code.=<<___				if ($PADLOCK_PREFETCH{$mode});
518e71b7053SJung-uk Kim	lea	($inp,$len),%rbp
519e71b7053SJung-uk Kim	neg	%rbp
520e71b7053SJung-uk Kim	and	\$0xfff,%rbp		# distance to page boundary
521e71b7053SJung-uk Kim	xor	%eax,%eax
522e71b7053SJung-uk Kim	cmp	\$$PADLOCK_PREFETCH{$mode},%rbp
523e71b7053SJung-uk Kim	mov	\$$PADLOCK_PREFETCH{$mode}-1,%rbp
524e71b7053SJung-uk Kim	cmovae	%rax,%rbp
525e71b7053SJung-uk Kim	and	$len,%rbp		# remainder
526e71b7053SJung-uk Kim	sub	%rbp,$len
527e71b7053SJung-uk Kim	jz	.L${mode}_aligned_tail
528e71b7053SJung-uk Kim___
529e71b7053SJung-uk Kim$code.=<<___;
530e71b7053SJung-uk Kim	lea	-16($ctx),%rax		# ivp
531e71b7053SJung-uk Kim	lea	16($ctx),%rbx		# key
532e71b7053SJung-uk Kim	shr	\$4,$len		# len/=AES_BLOCK_SIZE
533e71b7053SJung-uk Kim	.byte	0xf3,0x0f,0xa7,$opcode	# rep xcrypt*
534e71b7053SJung-uk Kim___
535e71b7053SJung-uk Kim$code.=<<___				if ($mode !~ /ecb|ctr/);
536e71b7053SJung-uk Kim	movdqa	(%rax),%xmm0
537e71b7053SJung-uk Kim	movdqa	%xmm0,-16($ctx)		# copy [or refresh] iv
538e71b7053SJung-uk Kim___
539e71b7053SJung-uk Kim$code.=<<___				if ($PADLOCK_PREFETCH{$mode});
540e71b7053SJung-uk Kim	test	%rbp,%rbp		# check remainder
541e71b7053SJung-uk Kim	jz	.L${mode}_exit
542e71b7053SJung-uk Kim
543e71b7053SJung-uk Kim.L${mode}_aligned_tail:
544e71b7053SJung-uk Kim	mov	$out,%r8
545e71b7053SJung-uk Kim	mov	%rbp,$chunk
546e71b7053SJung-uk Kim	mov	%rbp,$len
547e71b7053SJung-uk Kim	lea	(%rsp),%rbp
548e71b7053SJung-uk Kim	sub	$len,%rsp
549e71b7053SJung-uk Kim	shr	\$3,$len
550e71b7053SJung-uk Kim	lea	(%rsp),$out
551e71b7053SJung-uk Kim	.byte	0xf3,0x48,0xa5		# rep movsq
552e71b7053SJung-uk Kim	lea	(%r8),$out
553e71b7053SJung-uk Kim	lea	(%rsp),$inp
554e71b7053SJung-uk Kim	mov	$chunk,$len
555e71b7053SJung-uk Kim	jmp	.L${mode}_loop
556e71b7053SJung-uk Kim___
557e71b7053SJung-uk Kim$code.=<<___;
558e71b7053SJung-uk Kim.L${mode}_exit:
559e71b7053SJung-uk Kim	mov	\$1,%eax
560e71b7053SJung-uk Kim	lea	8(%rsp),%rsp
561e71b7053SJung-uk Kim.L${mode}_abort:
562e71b7053SJung-uk Kim	pop	%rbx
563e71b7053SJung-uk Kim	pop	%rbp
564e71b7053SJung-uk Kim	ret
565e71b7053SJung-uk Kim.size	padlock_${mode}_encrypt,.-padlock_${mode}_encrypt
566e71b7053SJung-uk Kim___
567e71b7053SJung-uk Kim}
568e71b7053SJung-uk Kim
569e71b7053SJung-uk Kim&generate_mode("ecb",0xc8);
570e71b7053SJung-uk Kim&generate_mode("cbc",0xd0);
571e71b7053SJung-uk Kim&generate_mode("cfb",0xe0);
572e71b7053SJung-uk Kim&generate_mode("ofb",0xe8);
573e71b7053SJung-uk Kim&generate_mode("ctr32",0xd8);	# all 64-bit CPUs have working CTR...
574e71b7053SJung-uk Kim
575e71b7053SJung-uk Kim$code.=<<___;
576e71b7053SJung-uk Kim.asciz	"VIA Padlock x86_64 module, CRYPTOGAMS by <appro\@openssl.org>"
577e71b7053SJung-uk Kim.align	16
578e71b7053SJung-uk Kim.data
579e71b7053SJung-uk Kim.align	8
580e71b7053SJung-uk Kim.Lpadlock_saved_context:
581e71b7053SJung-uk Kim	.quad	0
582e71b7053SJung-uk Kim___
583e71b7053SJung-uk Kim$code =~ s/\`([^\`]*)\`/eval($1)/gem;
584e71b7053SJung-uk Kim
585e71b7053SJung-uk Kimprint $code;
586e71b7053SJung-uk Kim
587e71b7053SJung-uk Kimclose STDOUT;
588