1e71b7053SJung-uk Kim#!/usr/bin/env perl
217f01e99SJung-uk Kim# Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim#
4b077aed3SPierre 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# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
11e71b7053SJung-uk Kim# project. The module is, however, dual licensed under OpenSSL and
12e71b7053SJung-uk Kim# CRYPTOGAMS licenses depending on where you obtain it. For further
13e71b7053SJung-uk Kim# details see http://www.openssl.org/~appro/cryptogams/.
14e71b7053SJung-uk Kim# ====================================================================
15e71b7053SJung-uk Kim#
16e71b7053SJung-uk Kim# X25519 lower-level primitives for x86_64.
17e71b7053SJung-uk Kim#
18e71b7053SJung-uk Kim# February 2018.
19e71b7053SJung-uk Kim#
20e71b7053SJung-uk Kim# This module implements radix 2^51 multiplication and squaring, and
21e71b7053SJung-uk Kim# radix 2^64 multiplication, squaring, addition, subtraction and final
22e71b7053SJung-uk Kim# reduction. Latter radix is used on ADCX/ADOX-capable processors such
23e71b7053SJung-uk Kim# as Broadwell. On related note one should mention that there are
24e71b7053SJung-uk Kim# vector implementations that provide significantly better performance
25e71b7053SJung-uk Kim# on some processors(*), but they are large and overly complex. Which
26e71b7053SJung-uk Kim# in combination with them being effectively processor-specific makes
27e71b7053SJung-uk Kim# the undertaking hard to justify. The goal for this implementation
28e71b7053SJung-uk Kim# is rather versatility and simplicity [and ultimately formal
29e71b7053SJung-uk Kim# verification].
30e71b7053SJung-uk Kim#
31e71b7053SJung-uk Kim# (*)	For example sandy2x should provide ~30% improvement on Sandy
32e71b7053SJung-uk Kim#	Bridge, but only nominal ~5% on Haswell [and big loss on
33e71b7053SJung-uk Kim#	Broadwell and successors].
34e71b7053SJung-uk Kim#
35e71b7053SJung-uk Kim######################################################################
36e71b7053SJung-uk Kim# Improvement coefficients:
37e71b7053SJung-uk Kim#
38e71b7053SJung-uk Kim#			amd64-51(*)	gcc-5.x(**)
39e71b7053SJung-uk Kim#
40e71b7053SJung-uk Kim# P4			+22%		+40%
41e71b7053SJung-uk Kim# Sandy Bridge		-3%		+11%
42e71b7053SJung-uk Kim# Haswell		-1%		+13%
43e71b7053SJung-uk Kim# Broadwell(***)	+30%		+35%
44e71b7053SJung-uk Kim# Skylake(***)		+33%		+47%
45e71b7053SJung-uk Kim# Silvermont		+20%		+26%
46e71b7053SJung-uk Kim# Goldmont		+40%		+50%
47e71b7053SJung-uk Kim# Bulldozer		+20%		+9%
48e71b7053SJung-uk Kim# Ryzen(***)		+43%		+40%
49e71b7053SJung-uk Kim# VIA			+170%		+120%
50e71b7053SJung-uk Kim#
51e71b7053SJung-uk Kim# (*)	amd64-51 is popular assembly implementation with 2^51 radix,
52e71b7053SJung-uk Kim#	only multiplication and squaring subroutines were linked
53e71b7053SJung-uk Kim#	for comparison, but not complete ladder step; gain on most
54e71b7053SJung-uk Kim#	processors is because this module refrains from shld, and
55e71b7053SJung-uk Kim#	minor regression on others is because this does result in
56e71b7053SJung-uk Kim#	higher instruction count;
57e71b7053SJung-uk Kim# (**)	compiler is free to inline functions, in assembly one would
58e71b7053SJung-uk Kim#	need to implement ladder step to do that, and it will improve
59e71b7053SJung-uk Kim#	performance by several percent;
60e71b7053SJung-uk Kim# (***)	ADCX/ADOX result for 2^64 radix, there is no corresponding
61e71b7053SJung-uk Kim#	C implementation, so that comparison is always against
62e71b7053SJung-uk Kim#	2^51 radix;
63e71b7053SJung-uk Kim
64b077aed3SPierre Pronchery# $output is the last argument if it looks like a file (it has an extension)
65b077aed3SPierre Pronchery# $flavour is the first argument if it doesn't look like a file
66b077aed3SPierre Pronchery$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
67b077aed3SPierre Pronchery$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
68e71b7053SJung-uk Kim
69e71b7053SJung-uk Kim$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
70e71b7053SJung-uk Kim
71e71b7053SJung-uk Kim$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
72e71b7053SJung-uk Kim( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
73e71b7053SJung-uk Kim( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
74e71b7053SJung-uk Kimdie "can't locate x86_64-xlate.pl";
75e71b7053SJung-uk Kim
76b077aed3SPierre Proncheryopen OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
77b077aed3SPierre Pronchery    or die "can't call $xlate: $!";
78e71b7053SJung-uk Kim*STDOUT=*OUT;
79e71b7053SJung-uk Kim
80e71b7053SJung-uk Kimif (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
81e71b7053SJung-uk Kim		=~ /GNU assembler version ([2-9]\.[0-9]+)/) {
82e71b7053SJung-uk Kim	$addx = ($1>=2.23);
83e71b7053SJung-uk Kim}
84e71b7053SJung-uk Kim
85e71b7053SJung-uk Kimif (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
86e71b7053SJung-uk Kim	    `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
87e71b7053SJung-uk Kim	$addx = ($1>=2.10);
88e71b7053SJung-uk Kim}
89e71b7053SJung-uk Kim
90e71b7053SJung-uk Kimif (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
91e71b7053SJung-uk Kim	    `ml64 2>&1` =~ /Version ([0-9]+)\./) {
92e71b7053SJung-uk Kim	$addx = ($1>=12);
93e71b7053SJung-uk Kim}
94e71b7053SJung-uk Kim
9563c1bb51SJung-uk Kimif (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0-9]+)\.([0-9]+)/) {
96e71b7053SJung-uk Kim	my $ver = $2 + $3/100.0;	# 3.1->3.01, 3.10->3.10
97e71b7053SJung-uk Kim	$addx = ($ver>=3.03);
98e71b7053SJung-uk Kim}
99e71b7053SJung-uk Kim
100e71b7053SJung-uk Kim$code.=<<___;
101e71b7053SJung-uk Kim.text
102e71b7053SJung-uk Kim
103e71b7053SJung-uk Kim.globl	x25519_fe51_mul
104e71b7053SJung-uk Kim.type	x25519_fe51_mul,\@function,3
105e71b7053SJung-uk Kim.align	32
106e71b7053SJung-uk Kimx25519_fe51_mul:
107e71b7053SJung-uk Kim.cfi_startproc
108e71b7053SJung-uk Kim	push	%rbp
109e71b7053SJung-uk Kim.cfi_push	%rbp
110e71b7053SJung-uk Kim	push	%rbx
111e71b7053SJung-uk Kim.cfi_push	%rbx
112e71b7053SJung-uk Kim	push	%r12
113e71b7053SJung-uk Kim.cfi_push	%r12
114e71b7053SJung-uk Kim	push	%r13
115e71b7053SJung-uk Kim.cfi_push	%r13
116e71b7053SJung-uk Kim	push	%r14
117e71b7053SJung-uk Kim.cfi_push	%r14
118e71b7053SJung-uk Kim	push	%r15
119e71b7053SJung-uk Kim.cfi_push	%r15
120e71b7053SJung-uk Kim	lea	-8*5(%rsp),%rsp
121e71b7053SJung-uk Kim.cfi_adjust_cfa_offset	40
122e71b7053SJung-uk Kim.Lfe51_mul_body:
123e71b7053SJung-uk Kim
124e71b7053SJung-uk Kim	mov	8*0(%rsi),%rax		# f[0]
125e71b7053SJung-uk Kim	mov	8*0(%rdx),%r11		# load g[0-4]
126e71b7053SJung-uk Kim	mov	8*1(%rdx),%r12
127e71b7053SJung-uk Kim	mov	8*2(%rdx),%r13
128e71b7053SJung-uk Kim	mov	8*3(%rdx),%rbp
129e71b7053SJung-uk Kim	mov	8*4(%rdx),%r14
130e71b7053SJung-uk Kim
131e71b7053SJung-uk Kim	mov	%rdi,8*4(%rsp)		# offload 1st argument
132e71b7053SJung-uk Kim	mov	%rax,%rdi
133e71b7053SJung-uk Kim	mulq	%r11			# f[0]*g[0]
134e71b7053SJung-uk Kim	mov	%r11,8*0(%rsp)		# offload g[0]
135e71b7053SJung-uk Kim	mov	%rax,%rbx		# %rbx:%rcx = h0
136e71b7053SJung-uk Kim	mov	%rdi,%rax
137e71b7053SJung-uk Kim	mov	%rdx,%rcx
138e71b7053SJung-uk Kim	mulq	%r12			# f[0]*g[1]
139e71b7053SJung-uk Kim	mov	%r12,8*1(%rsp)		# offload g[1]
140e71b7053SJung-uk Kim	mov	%rax,%r8		# %r8:%r9 = h1
141e71b7053SJung-uk Kim	mov	%rdi,%rax
142e71b7053SJung-uk Kim	lea	(%r14,%r14,8),%r15
143e71b7053SJung-uk Kim	mov	%rdx,%r9
144e71b7053SJung-uk Kim	mulq	%r13			# f[0]*g[2]
145e71b7053SJung-uk Kim	mov	%r13,8*2(%rsp)		# offload g[2]
146e71b7053SJung-uk Kim	mov	%rax,%r10		# %r10:%r11 = h2
147e71b7053SJung-uk Kim	mov	%rdi,%rax
148e71b7053SJung-uk Kim	lea	(%r14,%r15,2),%rdi	# g[4]*19
149e71b7053SJung-uk Kim	mov	%rdx,%r11
150e71b7053SJung-uk Kim	mulq	%rbp			# f[0]*g[3]
151e71b7053SJung-uk Kim	mov	%rax,%r12		# %r12:%r13 = h3
152e71b7053SJung-uk Kim	mov	8*0(%rsi),%rax		# f[0]
153e71b7053SJung-uk Kim	mov	%rdx,%r13
154e71b7053SJung-uk Kim	mulq	%r14			# f[0]*g[4]
155e71b7053SJung-uk Kim	mov	%rax,%r14		# %r14:%r15 = h4
156e71b7053SJung-uk Kim	mov	8*1(%rsi),%rax		# f[1]
157e71b7053SJung-uk Kim	mov	%rdx,%r15
158e71b7053SJung-uk Kim
159e71b7053SJung-uk Kim	mulq	%rdi			# f[1]*g[4]*19
160e71b7053SJung-uk Kim	add	%rax,%rbx
161e71b7053SJung-uk Kim	mov	8*2(%rsi),%rax		# f[2]
162e71b7053SJung-uk Kim	adc	%rdx,%rcx
163e71b7053SJung-uk Kim	mulq	%rdi			# f[2]*g[4]*19
164e71b7053SJung-uk Kim	add	%rax,%r8
165e71b7053SJung-uk Kim	mov	8*3(%rsi),%rax		# f[3]
166e71b7053SJung-uk Kim	adc	%rdx,%r9
167e71b7053SJung-uk Kim	mulq	%rdi			# f[3]*g[4]*19
168e71b7053SJung-uk Kim	add	%rax,%r10
169e71b7053SJung-uk Kim	mov	8*4(%rsi),%rax		# f[4]
170e71b7053SJung-uk Kim	adc	%rdx,%r11
171e71b7053SJung-uk Kim	mulq	%rdi			# f[4]*g[4]*19
172e71b7053SJung-uk Kim	imulq	\$19,%rbp,%rdi		# g[3]*19
173e71b7053SJung-uk Kim	add	%rax,%r12
174e71b7053SJung-uk Kim	mov	8*1(%rsi),%rax		# f[1]
175e71b7053SJung-uk Kim	adc	%rdx,%r13
176e71b7053SJung-uk Kim	mulq	%rbp			# f[1]*g[3]
177e71b7053SJung-uk Kim	mov	8*2(%rsp),%rbp		# g[2]
178e71b7053SJung-uk Kim	add	%rax,%r14
179e71b7053SJung-uk Kim	mov	8*2(%rsi),%rax		# f[2]
180e71b7053SJung-uk Kim	adc	%rdx,%r15
181e71b7053SJung-uk Kim
182e71b7053SJung-uk Kim	mulq	%rdi			# f[2]*g[3]*19
183e71b7053SJung-uk Kim	add	%rax,%rbx
184e71b7053SJung-uk Kim	mov	8*3(%rsi),%rax		# f[3]
185e71b7053SJung-uk Kim	adc	%rdx,%rcx
186e71b7053SJung-uk Kim	mulq	%rdi			# f[3]*g[3]*19
187e71b7053SJung-uk Kim	add	%rax,%r8
188e71b7053SJung-uk Kim	mov	8*4(%rsi),%rax		# f[4]
189e71b7053SJung-uk Kim	adc	%rdx,%r9
190e71b7053SJung-uk Kim	mulq	%rdi			# f[4]*g[3]*19
191e71b7053SJung-uk Kim	imulq	\$19,%rbp,%rdi		# g[2]*19
192e71b7053SJung-uk Kim	add	%rax,%r10
193e71b7053SJung-uk Kim	mov	8*1(%rsi),%rax		# f[1]
194e71b7053SJung-uk Kim	adc	%rdx,%r11
195e71b7053SJung-uk Kim	mulq	%rbp			# f[1]*g[2]
196e71b7053SJung-uk Kim	add	%rax,%r12
197e71b7053SJung-uk Kim	mov	8*2(%rsi),%rax		# f[2]
198e71b7053SJung-uk Kim	adc	%rdx,%r13
199e71b7053SJung-uk Kim	mulq	%rbp			# f[2]*g[2]
200e71b7053SJung-uk Kim	mov	8*1(%rsp),%rbp		# g[1]
201e71b7053SJung-uk Kim	add	%rax,%r14
202e71b7053SJung-uk Kim	mov	8*3(%rsi),%rax		# f[3]
203e71b7053SJung-uk Kim	adc	%rdx,%r15
204e71b7053SJung-uk Kim
205e71b7053SJung-uk Kim	mulq	%rdi			# f[3]*g[2]*19
206e71b7053SJung-uk Kim	add	%rax,%rbx
207e71b7053SJung-uk Kim	mov	8*4(%rsi),%rax		# f[3]
208e71b7053SJung-uk Kim	adc	%rdx,%rcx
209e71b7053SJung-uk Kim	mulq	%rdi			# f[4]*g[2]*19
210e71b7053SJung-uk Kim	add	%rax,%r8
211e71b7053SJung-uk Kim	mov	8*1(%rsi),%rax		# f[1]
212e71b7053SJung-uk Kim	adc	%rdx,%r9
213e71b7053SJung-uk Kim	mulq	%rbp			# f[1]*g[1]
214e71b7053SJung-uk Kim	imulq	\$19,%rbp,%rdi
215e71b7053SJung-uk Kim	add	%rax,%r10
216e71b7053SJung-uk Kim	mov	8*2(%rsi),%rax		# f[2]
217e71b7053SJung-uk Kim	adc	%rdx,%r11
218e71b7053SJung-uk Kim	mulq	%rbp			# f[2]*g[1]
219e71b7053SJung-uk Kim	add	%rax,%r12
220e71b7053SJung-uk Kim	mov	8*3(%rsi),%rax		# f[3]
221e71b7053SJung-uk Kim	adc	%rdx,%r13
222e71b7053SJung-uk Kim	mulq	%rbp			# f[3]*g[1]
223e71b7053SJung-uk Kim	mov	8*0(%rsp),%rbp		# g[0]
224e71b7053SJung-uk Kim	add	%rax,%r14
225e71b7053SJung-uk Kim	mov	8*4(%rsi),%rax		# f[4]
226e71b7053SJung-uk Kim	adc	%rdx,%r15
227e71b7053SJung-uk Kim
228e71b7053SJung-uk Kim	mulq	%rdi			# f[4]*g[1]*19
229e71b7053SJung-uk Kim	add	%rax,%rbx
230e71b7053SJung-uk Kim	mov	8*1(%rsi),%rax		# f[1]
231e71b7053SJung-uk Kim	adc	%rdx,%rcx
232e71b7053SJung-uk Kim	mul	%rbp			# f[1]*g[0]
233e71b7053SJung-uk Kim	add	%rax,%r8
234e71b7053SJung-uk Kim	mov	8*2(%rsi),%rax		# f[2]
235e71b7053SJung-uk Kim	adc	%rdx,%r9
236e71b7053SJung-uk Kim	mul	%rbp			# f[2]*g[0]
237e71b7053SJung-uk Kim	add	%rax,%r10
238e71b7053SJung-uk Kim	mov	8*3(%rsi),%rax		# f[3]
239e71b7053SJung-uk Kim	adc	%rdx,%r11
240e71b7053SJung-uk Kim	mul	%rbp			# f[3]*g[0]
241e71b7053SJung-uk Kim	add	%rax,%r12
242e71b7053SJung-uk Kim	mov	8*4(%rsi),%rax		# f[4]
243e71b7053SJung-uk Kim	adc	%rdx,%r13
244e71b7053SJung-uk Kim	mulq	%rbp			# f[4]*g[0]
245e71b7053SJung-uk Kim	add	%rax,%r14
246e71b7053SJung-uk Kim	adc	%rdx,%r15
247e71b7053SJung-uk Kim
248e71b7053SJung-uk Kim	mov	8*4(%rsp),%rdi		# restore 1st argument
249e71b7053SJung-uk Kim	jmp	.Lreduce51
250e71b7053SJung-uk Kim.Lfe51_mul_epilogue:
251e71b7053SJung-uk Kim.cfi_endproc
252e71b7053SJung-uk Kim.size	x25519_fe51_mul,.-x25519_fe51_mul
253e71b7053SJung-uk Kim
254e71b7053SJung-uk Kim.globl	x25519_fe51_sqr
255e71b7053SJung-uk Kim.type	x25519_fe51_sqr,\@function,2
256e71b7053SJung-uk Kim.align	32
257e71b7053SJung-uk Kimx25519_fe51_sqr:
258e71b7053SJung-uk Kim.cfi_startproc
259e71b7053SJung-uk Kim	push	%rbp
260e71b7053SJung-uk Kim.cfi_push	%rbp
261e71b7053SJung-uk Kim	push	%rbx
262e71b7053SJung-uk Kim.cfi_push	%rbx
263e71b7053SJung-uk Kim	push	%r12
264e71b7053SJung-uk Kim.cfi_push	%r12
265e71b7053SJung-uk Kim	push	%r13
266e71b7053SJung-uk Kim.cfi_push	%r13
267e71b7053SJung-uk Kim	push	%r14
268e71b7053SJung-uk Kim.cfi_push	%r14
269e71b7053SJung-uk Kim	push	%r15
270e71b7053SJung-uk Kim.cfi_push	%r15
271e71b7053SJung-uk Kim	lea	-8*5(%rsp),%rsp
272e71b7053SJung-uk Kim.cfi_adjust_cfa_offset	40
273e71b7053SJung-uk Kim.Lfe51_sqr_body:
274e71b7053SJung-uk Kim
275e71b7053SJung-uk Kim	mov	8*0(%rsi),%rax		# g[0]
276e71b7053SJung-uk Kim	mov	8*2(%rsi),%r15		# g[2]
277e71b7053SJung-uk Kim	mov	8*4(%rsi),%rbp		# g[4]
278e71b7053SJung-uk Kim
279e71b7053SJung-uk Kim	mov	%rdi,8*4(%rsp)		# offload 1st argument
280e71b7053SJung-uk Kim	lea	(%rax,%rax),%r14
281e71b7053SJung-uk Kim	mulq	%rax			# g[0]*g[0]
282e71b7053SJung-uk Kim	mov	%rax,%rbx
283e71b7053SJung-uk Kim	mov	8*1(%rsi),%rax		# g[1]
284e71b7053SJung-uk Kim	mov	%rdx,%rcx
285e71b7053SJung-uk Kim	mulq	%r14			# 2*g[0]*g[1]
286e71b7053SJung-uk Kim	mov	%rax,%r8
287e71b7053SJung-uk Kim	mov	%r15,%rax
288e71b7053SJung-uk Kim	mov	%r15,8*0(%rsp)		# offload g[2]
289e71b7053SJung-uk Kim	mov	%rdx,%r9
290e71b7053SJung-uk Kim	mulq	%r14			# 2*g[0]*g[2]
291e71b7053SJung-uk Kim	mov	%rax,%r10
292e71b7053SJung-uk Kim	mov	8*3(%rsi),%rax
293e71b7053SJung-uk Kim	mov	%rdx,%r11
294e71b7053SJung-uk Kim	imulq	\$19,%rbp,%rdi		# g[4]*19
295e71b7053SJung-uk Kim	mulq	%r14			# 2*g[0]*g[3]
296e71b7053SJung-uk Kim	mov	%rax,%r12
297e71b7053SJung-uk Kim	mov	%rbp,%rax
298e71b7053SJung-uk Kim	mov	%rdx,%r13
299e71b7053SJung-uk Kim	mulq	%r14			# 2*g[0]*g[4]
300e71b7053SJung-uk Kim	mov	%rax,%r14
301e71b7053SJung-uk Kim	mov	%rbp,%rax
302e71b7053SJung-uk Kim	mov	%rdx,%r15
303e71b7053SJung-uk Kim
304e71b7053SJung-uk Kim	mulq	%rdi			# g[4]*g[4]*19
305e71b7053SJung-uk Kim	add	%rax,%r12
306e71b7053SJung-uk Kim	mov	8*1(%rsi),%rax		# g[1]
307e71b7053SJung-uk Kim	adc	%rdx,%r13
308e71b7053SJung-uk Kim
309e71b7053SJung-uk Kim	mov	8*3(%rsi),%rsi		# g[3]
310e71b7053SJung-uk Kim	lea	(%rax,%rax),%rbp
311e71b7053SJung-uk Kim	mulq	%rax			# g[1]*g[1]
312e71b7053SJung-uk Kim	add	%rax,%r10
313e71b7053SJung-uk Kim	mov	8*0(%rsp),%rax		# g[2]
314e71b7053SJung-uk Kim	adc	%rdx,%r11
315e71b7053SJung-uk Kim	mulq	%rbp			# 2*g[1]*g[2]
316e71b7053SJung-uk Kim	add	%rax,%r12
317e71b7053SJung-uk Kim	mov	%rbp,%rax
318e71b7053SJung-uk Kim	adc	%rdx,%r13
319e71b7053SJung-uk Kim	mulq	%rsi			# 2*g[1]*g[3]
320e71b7053SJung-uk Kim	add	%rax,%r14
321e71b7053SJung-uk Kim	mov	%rbp,%rax
322e71b7053SJung-uk Kim	adc	%rdx,%r15
323e71b7053SJung-uk Kim	imulq	\$19,%rsi,%rbp		# g[3]*19
324e71b7053SJung-uk Kim	mulq	%rdi			# 2*g[1]*g[4]*19
325e71b7053SJung-uk Kim	add	%rax,%rbx
326e71b7053SJung-uk Kim	lea	(%rsi,%rsi),%rax
327e71b7053SJung-uk Kim	adc	%rdx,%rcx
328e71b7053SJung-uk Kim
329e71b7053SJung-uk Kim	mulq	%rdi			# 2*g[3]*g[4]*19
330e71b7053SJung-uk Kim	add	%rax,%r10
331e71b7053SJung-uk Kim	mov	%rsi,%rax
332e71b7053SJung-uk Kim	adc	%rdx,%r11
333e71b7053SJung-uk Kim	mulq	%rbp			# g[3]*g[3]*19
334e71b7053SJung-uk Kim	add	%rax,%r8
335e71b7053SJung-uk Kim	mov	8*0(%rsp),%rax		# g[2]
336e71b7053SJung-uk Kim	adc	%rdx,%r9
337e71b7053SJung-uk Kim
338e71b7053SJung-uk Kim	lea	(%rax,%rax),%rsi
339e71b7053SJung-uk Kim	mulq	%rax			# g[2]*g[2]
340e71b7053SJung-uk Kim	add	%rax,%r14
341e71b7053SJung-uk Kim	mov	%rbp,%rax
342e71b7053SJung-uk Kim	adc	%rdx,%r15
343e71b7053SJung-uk Kim	mulq	%rsi			# 2*g[2]*g[3]*19
344e71b7053SJung-uk Kim	add	%rax,%rbx
345e71b7053SJung-uk Kim	mov	%rsi,%rax
346e71b7053SJung-uk Kim	adc	%rdx,%rcx
347e71b7053SJung-uk Kim	mulq	%rdi			# 2*g[2]*g[4]*19
348e71b7053SJung-uk Kim	add	%rax,%r8
349e71b7053SJung-uk Kim	adc	%rdx,%r9
350e71b7053SJung-uk Kim
351e71b7053SJung-uk Kim	mov	8*4(%rsp),%rdi		# restore 1st argument
352e71b7053SJung-uk Kim	jmp	.Lreduce51
353e71b7053SJung-uk Kim
354e71b7053SJung-uk Kim.align	32
355e71b7053SJung-uk Kim.Lreduce51:
356e71b7053SJung-uk Kim	mov	\$0x7ffffffffffff,%rbp
357e71b7053SJung-uk Kim
358e71b7053SJung-uk Kim	mov	%r10,%rdx
359e71b7053SJung-uk Kim	shr	\$51,%r10
360e71b7053SJung-uk Kim	shl	\$13,%r11
361e71b7053SJung-uk Kim	and	%rbp,%rdx		# %rdx = g2 = h2 & mask
362e71b7053SJung-uk Kim	or	%r10,%r11		# h2>>51
363e71b7053SJung-uk Kim	add	%r11,%r12
364e71b7053SJung-uk Kim	adc	\$0,%r13		# h3 += h2>>51
365e71b7053SJung-uk Kim
366e71b7053SJung-uk Kim	mov	%rbx,%rax
367e71b7053SJung-uk Kim	shr	\$51,%rbx
368e71b7053SJung-uk Kim	shl	\$13,%rcx
369e71b7053SJung-uk Kim	and	%rbp,%rax		# %rax = g0 = h0 & mask
370e71b7053SJung-uk Kim	or	%rbx,%rcx		# h0>>51
371e71b7053SJung-uk Kim	add	%rcx,%r8		# h1 += h0>>51
372e71b7053SJung-uk Kim	adc	\$0,%r9
373e71b7053SJung-uk Kim
374e71b7053SJung-uk Kim	mov	%r12,%rbx
375e71b7053SJung-uk Kim	shr	\$51,%r12
376e71b7053SJung-uk Kim	shl	\$13,%r13
377e71b7053SJung-uk Kim	and	%rbp,%rbx		# %rbx = g3 = h3 & mask
378e71b7053SJung-uk Kim	or	%r12,%r13		# h3>>51
379e71b7053SJung-uk Kim	add	%r13,%r14		# h4 += h3>>51
380e71b7053SJung-uk Kim	adc	\$0,%r15
381e71b7053SJung-uk Kim
382e71b7053SJung-uk Kim	mov	%r8,%rcx
383e71b7053SJung-uk Kim	shr	\$51,%r8
384e71b7053SJung-uk Kim	shl	\$13,%r9
385e71b7053SJung-uk Kim	and	%rbp,%rcx		# %rcx = g1 = h1 & mask
386e71b7053SJung-uk Kim	or	%r8,%r9
387e71b7053SJung-uk Kim	add	%r9,%rdx		# g2 += h1>>51
388e71b7053SJung-uk Kim
389e71b7053SJung-uk Kim	mov	%r14,%r10
390e71b7053SJung-uk Kim	shr	\$51,%r14
391e71b7053SJung-uk Kim	shl	\$13,%r15
392e71b7053SJung-uk Kim	and	%rbp,%r10		# %r10 = g4 = h0 & mask
393e71b7053SJung-uk Kim	or	%r14,%r15		# h0>>51
394e71b7053SJung-uk Kim
395e71b7053SJung-uk Kim	lea	(%r15,%r15,8),%r14
396e71b7053SJung-uk Kim	lea	(%r15,%r14,2),%r15
397e71b7053SJung-uk Kim	add	%r15,%rax		# g0 += (h0>>51)*19
398e71b7053SJung-uk Kim
399e71b7053SJung-uk Kim	mov	%rdx,%r8
400e71b7053SJung-uk Kim	and	%rbp,%rdx		# g2 &= mask
401e71b7053SJung-uk Kim	shr	\$51,%r8
402e71b7053SJung-uk Kim	add	%r8,%rbx		# g3 += g2>>51
403e71b7053SJung-uk Kim
404e71b7053SJung-uk Kim	mov	%rax,%r9
405e71b7053SJung-uk Kim	and	%rbp,%rax		# g0 &= mask
406e71b7053SJung-uk Kim	shr	\$51,%r9
407e71b7053SJung-uk Kim	add	%r9,%rcx		# g1 += g0>>51
408e71b7053SJung-uk Kim
409e71b7053SJung-uk Kim	mov	%rax,8*0(%rdi)		# save the result
410e71b7053SJung-uk Kim	mov	%rcx,8*1(%rdi)
411e71b7053SJung-uk Kim	mov	%rdx,8*2(%rdi)
412e71b7053SJung-uk Kim	mov	%rbx,8*3(%rdi)
413e71b7053SJung-uk Kim	mov	%r10,8*4(%rdi)
414e71b7053SJung-uk Kim
415e71b7053SJung-uk Kim	mov	8*5(%rsp),%r15
416e71b7053SJung-uk Kim.cfi_restore	%r15
417e71b7053SJung-uk Kim	mov	8*6(%rsp),%r14
418e71b7053SJung-uk Kim.cfi_restore	%r14
419e71b7053SJung-uk Kim	mov	8*7(%rsp),%r13
420e71b7053SJung-uk Kim.cfi_restore	%r13
421e71b7053SJung-uk Kim	mov	8*8(%rsp),%r12
422e71b7053SJung-uk Kim.cfi_restore	%r12
423e71b7053SJung-uk Kim	mov	8*9(%rsp),%rbx
424e71b7053SJung-uk Kim.cfi_restore	%rbx
425e71b7053SJung-uk Kim	mov	8*10(%rsp),%rbp
426e71b7053SJung-uk Kim.cfi_restore	%rbp
427e71b7053SJung-uk Kim	lea	8*11(%rsp),%rsp
428e71b7053SJung-uk Kim.cfi_adjust_cfa_offset	88
429e71b7053SJung-uk Kim.Lfe51_sqr_epilogue:
430e71b7053SJung-uk Kim	ret
431e71b7053SJung-uk Kim.cfi_endproc
432e71b7053SJung-uk Kim.size	x25519_fe51_sqr,.-x25519_fe51_sqr
433e71b7053SJung-uk Kim
434e71b7053SJung-uk Kim.globl	x25519_fe51_mul121666
435e71b7053SJung-uk Kim.type	x25519_fe51_mul121666,\@function,2
436e71b7053SJung-uk Kim.align	32
437e71b7053SJung-uk Kimx25519_fe51_mul121666:
438e71b7053SJung-uk Kim.cfi_startproc
439e71b7053SJung-uk Kim	push	%rbp
440e71b7053SJung-uk Kim.cfi_push	%rbp
441e71b7053SJung-uk Kim	push	%rbx
442e71b7053SJung-uk Kim.cfi_push	%rbx
443e71b7053SJung-uk Kim	push	%r12
444e71b7053SJung-uk Kim.cfi_push	%r12
445e71b7053SJung-uk Kim	push	%r13
446e71b7053SJung-uk Kim.cfi_push	%r13
447e71b7053SJung-uk Kim	push	%r14
448e71b7053SJung-uk Kim.cfi_push	%r14
449e71b7053SJung-uk Kim	push	%r15
450e71b7053SJung-uk Kim.cfi_push	%r15
451e71b7053SJung-uk Kim	lea	-8*5(%rsp),%rsp
452e71b7053SJung-uk Kim.cfi_adjust_cfa_offset	40
453e71b7053SJung-uk Kim.Lfe51_mul121666_body:
454e71b7053SJung-uk Kim	mov	\$121666,%eax
455e71b7053SJung-uk Kim
456e71b7053SJung-uk Kim	mulq	8*0(%rsi)
457e71b7053SJung-uk Kim	mov	%rax,%rbx		# %rbx:%rcx = h0
458e71b7053SJung-uk Kim	mov	\$121666,%eax
459e71b7053SJung-uk Kim	mov	%rdx,%rcx
460e71b7053SJung-uk Kim	mulq	8*1(%rsi)
461e71b7053SJung-uk Kim	mov	%rax,%r8		# %r8:%r9 = h1
462e71b7053SJung-uk Kim	mov	\$121666,%eax
463e71b7053SJung-uk Kim	mov	%rdx,%r9
464e71b7053SJung-uk Kim	mulq	8*2(%rsi)
465e71b7053SJung-uk Kim	mov	%rax,%r10		# %r10:%r11 = h2
466e71b7053SJung-uk Kim	mov	\$121666,%eax
467e71b7053SJung-uk Kim	mov	%rdx,%r11
468e71b7053SJung-uk Kim	mulq	8*3(%rsi)
469e71b7053SJung-uk Kim	mov	%rax,%r12		# %r12:%r13 = h3
470e71b7053SJung-uk Kim	mov	\$121666,%eax		# f[0]
471e71b7053SJung-uk Kim	mov	%rdx,%r13
472e71b7053SJung-uk Kim	mulq	8*4(%rsi)
473e71b7053SJung-uk Kim	mov	%rax,%r14		# %r14:%r15 = h4
474e71b7053SJung-uk Kim	mov	%rdx,%r15
475e71b7053SJung-uk Kim
476e71b7053SJung-uk Kim	jmp	.Lreduce51
477e71b7053SJung-uk Kim.Lfe51_mul121666_epilogue:
478e71b7053SJung-uk Kim.cfi_endproc
479e71b7053SJung-uk Kim.size	x25519_fe51_mul121666,.-x25519_fe51_mul121666
480e71b7053SJung-uk Kim___
481e71b7053SJung-uk Kim########################################################################
482e71b7053SJung-uk Kim# Base 2^64 subroutines modulo 2*(2^255-19)
483e71b7053SJung-uk Kim#
484e71b7053SJung-uk Kimif ($addx) {
485e71b7053SJung-uk Kimmy ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7) = map("%r$_",(8..15));
486e71b7053SJung-uk Kim
487e71b7053SJung-uk Kim$code.=<<___;
488e71b7053SJung-uk Kim.extern	OPENSSL_ia32cap_P
489e71b7053SJung-uk Kim.globl	x25519_fe64_eligible
490e71b7053SJung-uk Kim.type	x25519_fe64_eligible,\@abi-omnipotent
491e71b7053SJung-uk Kim.align	32
492e71b7053SJung-uk Kimx25519_fe64_eligible:
49317f01e99SJung-uk Kim.cfi_startproc
494e71b7053SJung-uk Kim	mov	OPENSSL_ia32cap_P+8(%rip),%ecx
495e71b7053SJung-uk Kim	xor	%eax,%eax
496e71b7053SJung-uk Kim	and	\$0x80100,%ecx
497e71b7053SJung-uk Kim	cmp	\$0x80100,%ecx
498e71b7053SJung-uk Kim	cmove	%ecx,%eax
499e71b7053SJung-uk Kim	ret
50017f01e99SJung-uk Kim.cfi_endproc
501e71b7053SJung-uk Kim.size	x25519_fe64_eligible,.-x25519_fe64_eligible
502e71b7053SJung-uk Kim
503e71b7053SJung-uk Kim.globl	x25519_fe64_mul
504e71b7053SJung-uk Kim.type	x25519_fe64_mul,\@function,3
505e71b7053SJung-uk Kim.align	32
506e71b7053SJung-uk Kimx25519_fe64_mul:
507e71b7053SJung-uk Kim.cfi_startproc
508e71b7053SJung-uk Kim	push	%rbp
509e71b7053SJung-uk Kim.cfi_push	%rbp
510e71b7053SJung-uk Kim	push	%rbx
511e71b7053SJung-uk Kim.cfi_push	%rbx
512e71b7053SJung-uk Kim	push	%r12
513e71b7053SJung-uk Kim.cfi_push	%r12
514e71b7053SJung-uk Kim	push	%r13
515e71b7053SJung-uk Kim.cfi_push	%r13
516e71b7053SJung-uk Kim	push	%r14
517e71b7053SJung-uk Kim.cfi_push	%r14
518e71b7053SJung-uk Kim	push	%r15
519e71b7053SJung-uk Kim.cfi_push	%r15
520e71b7053SJung-uk Kim	push	%rdi			# offload dst
521e71b7053SJung-uk Kim.cfi_push	%rdi
522e71b7053SJung-uk Kim	lea	-8*2(%rsp),%rsp
523e71b7053SJung-uk Kim.cfi_adjust_cfa_offset	16
524e71b7053SJung-uk Kim.Lfe64_mul_body:
525e71b7053SJung-uk Kim
526e71b7053SJung-uk Kim	mov	%rdx,%rax
527e71b7053SJung-uk Kim	mov	8*0(%rdx),%rbp		# b[0]
528e71b7053SJung-uk Kim	mov	8*0(%rsi),%rdx		# a[0]
529e71b7053SJung-uk Kim	mov	8*1(%rax),%rcx		# b[1]
530e71b7053SJung-uk Kim	mov	8*2(%rax),$acc6		# b[2]
531e71b7053SJung-uk Kim	mov	8*3(%rax),$acc7		# b[3]
532e71b7053SJung-uk Kim
533e71b7053SJung-uk Kim	mulx	%rbp,$acc0,%rax		# a[0]*b[0]
534e71b7053SJung-uk Kim	xor	%edi,%edi		# cf=0,of=0
535e71b7053SJung-uk Kim	mulx	%rcx,$acc1,%rbx		# a[0]*b[1]
536e71b7053SJung-uk Kim	adcx	%rax,$acc1
537e71b7053SJung-uk Kim	mulx	$acc6,$acc2,%rax	# a[0]*b[2]
538e71b7053SJung-uk Kim	adcx	%rbx,$acc2
539e71b7053SJung-uk Kim	mulx	$acc7,$acc3,$acc4	# a[0]*b[3]
540e71b7053SJung-uk Kim	 mov	8*1(%rsi),%rdx		# a[1]
541e71b7053SJung-uk Kim	adcx	%rax,$acc3
542e71b7053SJung-uk Kim	mov	$acc6,(%rsp)		# offload b[2]
543e71b7053SJung-uk Kim	adcx	%rdi,$acc4		# cf=0
544e71b7053SJung-uk Kim
545e71b7053SJung-uk Kim	mulx	%rbp,%rax,%rbx		# a[1]*b[0]
546e71b7053SJung-uk Kim	adox	%rax,$acc1
547e71b7053SJung-uk Kim	adcx	%rbx,$acc2
548e71b7053SJung-uk Kim	mulx	%rcx,%rax,%rbx		# a[1]*b[1]
549e71b7053SJung-uk Kim	adox	%rax,$acc2
550e71b7053SJung-uk Kim	adcx	%rbx,$acc3
551e71b7053SJung-uk Kim	mulx	$acc6,%rax,%rbx		# a[1]*b[2]
552e71b7053SJung-uk Kim	adox	%rax,$acc3
553e71b7053SJung-uk Kim	adcx	%rbx,$acc4
554e71b7053SJung-uk Kim	mulx	$acc7,%rax,$acc5	# a[1]*b[3]
555e71b7053SJung-uk Kim	 mov	8*2(%rsi),%rdx		# a[2]
556e71b7053SJung-uk Kim	adox	%rax,$acc4
557e71b7053SJung-uk Kim	adcx	%rdi,$acc5		# cf=0
558e71b7053SJung-uk Kim	adox	%rdi,$acc5		# of=0
559e71b7053SJung-uk Kim
560e71b7053SJung-uk Kim	mulx	%rbp,%rax,%rbx		# a[2]*b[0]
561e71b7053SJung-uk Kim	adcx	%rax,$acc2
562e71b7053SJung-uk Kim	adox	%rbx,$acc3
563e71b7053SJung-uk Kim	mulx	%rcx,%rax,%rbx		# a[2]*b[1]
564e71b7053SJung-uk Kim	adcx	%rax,$acc3
565e71b7053SJung-uk Kim	adox	%rbx,$acc4
566e71b7053SJung-uk Kim	mulx	$acc6,%rax,%rbx		# a[2]*b[2]
567e71b7053SJung-uk Kim	adcx	%rax,$acc4
568e71b7053SJung-uk Kim	adox	%rbx,$acc5
569e71b7053SJung-uk Kim	mulx	$acc7,%rax,$acc6	# a[2]*b[3]
570e71b7053SJung-uk Kim	 mov	8*3(%rsi),%rdx		# a[3]
571e71b7053SJung-uk Kim	adcx	%rax,$acc5
572e71b7053SJung-uk Kim	adox	%rdi,$acc6		# of=0
573e71b7053SJung-uk Kim	adcx	%rdi,$acc6		# cf=0
574e71b7053SJung-uk Kim
575e71b7053SJung-uk Kim	mulx	%rbp,%rax,%rbx		# a[3]*b[0]
576e71b7053SJung-uk Kim	adox	%rax,$acc3
577e71b7053SJung-uk Kim	adcx	%rbx,$acc4
578e71b7053SJung-uk Kim	mulx	%rcx,%rax,%rbx		# a[3]*b[1]
579e71b7053SJung-uk Kim	adox	%rax,$acc4
580e71b7053SJung-uk Kim	adcx	%rbx,$acc5
581e71b7053SJung-uk Kim	mulx	(%rsp),%rax,%rbx	# a[3]*b[2]
582e71b7053SJung-uk Kim	adox	%rax,$acc5
583e71b7053SJung-uk Kim	adcx	%rbx,$acc6
584e71b7053SJung-uk Kim	mulx	$acc7,%rax,$acc7	# a[3]*b[3]
585e71b7053SJung-uk Kim	 mov	\$38,%edx
586e71b7053SJung-uk Kim	adox	%rax,$acc6
587e71b7053SJung-uk Kim	adcx	%rdi,$acc7		# cf=0
588e71b7053SJung-uk Kim	adox	%rdi,$acc7		# of=0
589e71b7053SJung-uk Kim
590e71b7053SJung-uk Kim	jmp	.Lreduce64
591e71b7053SJung-uk Kim.Lfe64_mul_epilogue:
592e71b7053SJung-uk Kim.cfi_endproc
593e71b7053SJung-uk Kim.size	x25519_fe64_mul,.-x25519_fe64_mul
594e71b7053SJung-uk Kim
595e71b7053SJung-uk Kim.globl	x25519_fe64_sqr
596e71b7053SJung-uk Kim.type	x25519_fe64_sqr,\@function,2
597e71b7053SJung-uk Kim.align	32
598e71b7053SJung-uk Kimx25519_fe64_sqr:
599e71b7053SJung-uk Kim.cfi_startproc
600e71b7053SJung-uk Kim	push	%rbp
601e71b7053SJung-uk Kim.cfi_push	%rbp
602e71b7053SJung-uk Kim	push	%rbx
603e71b7053SJung-uk Kim.cfi_push	%rbx
604e71b7053SJung-uk Kim	push	%r12
605e71b7053SJung-uk Kim.cfi_push	%r12
606e71b7053SJung-uk Kim	push	%r13
607e71b7053SJung-uk Kim.cfi_push	%r13
608e71b7053SJung-uk Kim	push	%r14
609e71b7053SJung-uk Kim.cfi_push	%r14
610e71b7053SJung-uk Kim	push	%r15
611e71b7053SJung-uk Kim.cfi_push	%r15
612e71b7053SJung-uk Kim	push	%rdi			# offload dst
613e71b7053SJung-uk Kim.cfi_push	%rdi
614e71b7053SJung-uk Kim	lea	-8*2(%rsp),%rsp
615e71b7053SJung-uk Kim.cfi_adjust_cfa_offset	16
616e71b7053SJung-uk Kim.Lfe64_sqr_body:
617e71b7053SJung-uk Kim
618e71b7053SJung-uk Kim	mov	8*0(%rsi),%rdx		# a[0]
619e71b7053SJung-uk Kim	mov	8*1(%rsi),%rcx		# a[1]
620e71b7053SJung-uk Kim	mov	8*2(%rsi),%rbp		# a[2]
621e71b7053SJung-uk Kim	mov	8*3(%rsi),%rsi		# a[3]
622e71b7053SJung-uk Kim
623e71b7053SJung-uk Kim	################################################################
624e71b7053SJung-uk Kim	mulx	%rdx,$acc0,$acc7	# a[0]*a[0]
625e71b7053SJung-uk Kim	mulx	%rcx,$acc1,%rax		# a[0]*a[1]
626e71b7053SJung-uk Kim	xor	%edi,%edi		# cf=0,of=0
627e71b7053SJung-uk Kim	mulx	%rbp,$acc2,%rbx		# a[0]*a[2]
628e71b7053SJung-uk Kim	adcx	%rax,$acc2
629e71b7053SJung-uk Kim	mulx	%rsi,$acc3,$acc4	# a[0]*a[3]
630e71b7053SJung-uk Kim	 mov	%rcx,%rdx		# a[1]
631e71b7053SJung-uk Kim	adcx	%rbx,$acc3
632e71b7053SJung-uk Kim	adcx	%rdi,$acc4		# cf=0
633e71b7053SJung-uk Kim
634e71b7053SJung-uk Kim	################################################################
635e71b7053SJung-uk Kim	mulx	%rbp,%rax,%rbx		# a[1]*a[2]
636e71b7053SJung-uk Kim	adox	%rax,$acc3
637e71b7053SJung-uk Kim	adcx	%rbx,$acc4
638e71b7053SJung-uk Kim	mulx	%rsi,%rax,$acc5		# a[1]*a[3]
639e71b7053SJung-uk Kim	 mov	%rbp,%rdx		# a[2]
640e71b7053SJung-uk Kim	adox	%rax,$acc4
641e71b7053SJung-uk Kim	adcx	%rdi,$acc5
642e71b7053SJung-uk Kim
643e71b7053SJung-uk Kim	################################################################
644e71b7053SJung-uk Kim	mulx	%rsi,%rax,$acc6		# a[2]*a[3]
645e71b7053SJung-uk Kim	 mov	%rcx,%rdx		# a[1]
646e71b7053SJung-uk Kim	adox	%rax,$acc5
647e71b7053SJung-uk Kim	adcx	%rdi,$acc6		# cf=0
648e71b7053SJung-uk Kim	adox	%rdi,$acc6		# of=0
649e71b7053SJung-uk Kim
650e71b7053SJung-uk Kim	 adcx	$acc1,$acc1		# acc1:6<<1
651e71b7053SJung-uk Kim	adox	$acc7,$acc1
652e71b7053SJung-uk Kim	 adcx	$acc2,$acc2
653e71b7053SJung-uk Kim	mulx	%rdx,%rax,%rbx		# a[1]*a[1]
654e71b7053SJung-uk Kim	 mov	%rbp,%rdx		# a[2]
655e71b7053SJung-uk Kim	 adcx	$acc3,$acc3
656e71b7053SJung-uk Kim	adox	%rax,$acc2
657e71b7053SJung-uk Kim	 adcx	$acc4,$acc4
658e71b7053SJung-uk Kim	adox	%rbx,$acc3
659e71b7053SJung-uk Kim	mulx	%rdx,%rax,%rbx		# a[2]*a[2]
660e71b7053SJung-uk Kim	 mov	%rsi,%rdx		# a[3]
661e71b7053SJung-uk Kim	 adcx	$acc5,$acc5
662e71b7053SJung-uk Kim	adox	%rax,$acc4
663e71b7053SJung-uk Kim	 adcx	$acc6,$acc6
664e71b7053SJung-uk Kim	adox	%rbx,$acc5
665e71b7053SJung-uk Kim	mulx	%rdx,%rax,$acc7		# a[3]*a[3]
666e71b7053SJung-uk Kim	 mov	\$38,%edx
667e71b7053SJung-uk Kim	adox	%rax,$acc6
668e71b7053SJung-uk Kim	adcx	%rdi,$acc7		# cf=0
669e71b7053SJung-uk Kim	adox	%rdi,$acc7		# of=0
670e71b7053SJung-uk Kim	jmp	.Lreduce64
671e71b7053SJung-uk Kim
672e71b7053SJung-uk Kim.align	32
673e71b7053SJung-uk Kim.Lreduce64:
674e71b7053SJung-uk Kim	mulx	$acc4,%rax,%rbx
675e71b7053SJung-uk Kim	adcx	%rax,$acc0
676e71b7053SJung-uk Kim	adox	%rbx,$acc1
677e71b7053SJung-uk Kim	mulx	$acc5,%rax,%rbx
678e71b7053SJung-uk Kim	adcx	%rax,$acc1
679e71b7053SJung-uk Kim	adox	%rbx,$acc2
680e71b7053SJung-uk Kim	mulx	$acc6,%rax,%rbx
681e71b7053SJung-uk Kim	adcx	%rax,$acc2
682e71b7053SJung-uk Kim	adox	%rbx,$acc3
683e71b7053SJung-uk Kim	mulx	$acc7,%rax,$acc4
684e71b7053SJung-uk Kim	adcx	%rax,$acc3
685e71b7053SJung-uk Kim	adox	%rdi,$acc4
686e71b7053SJung-uk Kim	adcx	%rdi,$acc4
687e71b7053SJung-uk Kim
688e71b7053SJung-uk Kim	mov	8*2(%rsp),%rdi		# restore dst
689e71b7053SJung-uk Kim	imulq	%rdx,$acc4
690e71b7053SJung-uk Kim
691e71b7053SJung-uk Kim	add	$acc4,$acc0
692e71b7053SJung-uk Kim	adc	\$0,$acc1
693e71b7053SJung-uk Kim	adc	\$0,$acc2
694e71b7053SJung-uk Kim	adc	\$0,$acc3
695e71b7053SJung-uk Kim
696e71b7053SJung-uk Kim	sbb	%rax,%rax		# cf -> mask
697e71b7053SJung-uk Kim	and	\$38,%rax
698e71b7053SJung-uk Kim
699e71b7053SJung-uk Kim	add	%rax,$acc0
700e71b7053SJung-uk Kim	mov	$acc1,8*1(%rdi)
701e71b7053SJung-uk Kim	mov	$acc2,8*2(%rdi)
702e71b7053SJung-uk Kim	mov	$acc3,8*3(%rdi)
703e71b7053SJung-uk Kim	mov	$acc0,8*0(%rdi)
704e71b7053SJung-uk Kim
705e71b7053SJung-uk Kim	mov	8*3(%rsp),%r15
706e71b7053SJung-uk Kim.cfi_restore	%r15
707e71b7053SJung-uk Kim	mov	8*4(%rsp),%r14
708e71b7053SJung-uk Kim.cfi_restore	%r14
709e71b7053SJung-uk Kim	mov	8*5(%rsp),%r13
710e71b7053SJung-uk Kim.cfi_restore	%r13
711e71b7053SJung-uk Kim	mov	8*6(%rsp),%r12
712e71b7053SJung-uk Kim.cfi_restore	%r12
713e71b7053SJung-uk Kim	mov	8*7(%rsp),%rbx
714e71b7053SJung-uk Kim.cfi_restore	%rbx
715e71b7053SJung-uk Kim	mov	8*8(%rsp),%rbp
716e71b7053SJung-uk Kim.cfi_restore	%rbp
717e71b7053SJung-uk Kim	lea	8*9(%rsp),%rsp
718e71b7053SJung-uk Kim.cfi_adjust_cfa_offset	88
719e71b7053SJung-uk Kim.Lfe64_sqr_epilogue:
720e71b7053SJung-uk Kim	ret
721e71b7053SJung-uk Kim.cfi_endproc
722e71b7053SJung-uk Kim.size	x25519_fe64_sqr,.-x25519_fe64_sqr
723e71b7053SJung-uk Kim
724e71b7053SJung-uk Kim.globl	x25519_fe64_mul121666
725e71b7053SJung-uk Kim.type	x25519_fe64_mul121666,\@function,2
726e71b7053SJung-uk Kim.align	32
727e71b7053SJung-uk Kimx25519_fe64_mul121666:
728e71b7053SJung-uk Kim.Lfe64_mul121666_body:
72917f01e99SJung-uk Kim.cfi_startproc
730e71b7053SJung-uk Kim	mov	\$121666,%edx
731e71b7053SJung-uk Kim	mulx	8*0(%rsi),$acc0,%rcx
732e71b7053SJung-uk Kim	mulx	8*1(%rsi),$acc1,%rax
733e71b7053SJung-uk Kim	add	%rcx,$acc1
734e71b7053SJung-uk Kim	mulx	8*2(%rsi),$acc2,%rcx
735e71b7053SJung-uk Kim	adc	%rax,$acc2
736e71b7053SJung-uk Kim	mulx	8*3(%rsi),$acc3,%rax
737e71b7053SJung-uk Kim	adc	%rcx,$acc3
738e71b7053SJung-uk Kim	adc	\$0,%rax
739e71b7053SJung-uk Kim
740e71b7053SJung-uk Kim	imulq	\$38,%rax,%rax
741e71b7053SJung-uk Kim
742e71b7053SJung-uk Kim	add	%rax,$acc0
743e71b7053SJung-uk Kim	adc	\$0,$acc1
744e71b7053SJung-uk Kim	adc	\$0,$acc2
745e71b7053SJung-uk Kim	adc	\$0,$acc3
746e71b7053SJung-uk Kim
747e71b7053SJung-uk Kim	sbb	%rax,%rax		# cf -> mask
748e71b7053SJung-uk Kim	and	\$38,%rax
749e71b7053SJung-uk Kim
750e71b7053SJung-uk Kim	add	%rax,$acc0
751e71b7053SJung-uk Kim	mov	$acc1,8*1(%rdi)
752e71b7053SJung-uk Kim	mov	$acc2,8*2(%rdi)
753e71b7053SJung-uk Kim	mov	$acc3,8*3(%rdi)
754e71b7053SJung-uk Kim	mov	$acc0,8*0(%rdi)
755e71b7053SJung-uk Kim
756e71b7053SJung-uk Kim.Lfe64_mul121666_epilogue:
757e71b7053SJung-uk Kim	ret
75817f01e99SJung-uk Kim.cfi_endproc
759e71b7053SJung-uk Kim.size	x25519_fe64_mul121666,.-x25519_fe64_mul121666
760e71b7053SJung-uk Kim
761e71b7053SJung-uk Kim.globl	x25519_fe64_add
762e71b7053SJung-uk Kim.type	x25519_fe64_add,\@function,3
763e71b7053SJung-uk Kim.align	32
764e71b7053SJung-uk Kimx25519_fe64_add:
765e71b7053SJung-uk Kim.Lfe64_add_body:
76617f01e99SJung-uk Kim.cfi_startproc
767e71b7053SJung-uk Kim	mov	8*0(%rsi),$acc0
768e71b7053SJung-uk Kim	mov	8*1(%rsi),$acc1
769e71b7053SJung-uk Kim	mov	8*2(%rsi),$acc2
770e71b7053SJung-uk Kim	mov	8*3(%rsi),$acc3
771e71b7053SJung-uk Kim
772e71b7053SJung-uk Kim	add	8*0(%rdx),$acc0
773e71b7053SJung-uk Kim	adc	8*1(%rdx),$acc1
774e71b7053SJung-uk Kim	adc	8*2(%rdx),$acc2
775e71b7053SJung-uk Kim	adc	8*3(%rdx),$acc3
776e71b7053SJung-uk Kim
777e71b7053SJung-uk Kim	sbb	%rax,%rax		# cf -> mask
778e71b7053SJung-uk Kim	and	\$38,%rax
779e71b7053SJung-uk Kim
780e71b7053SJung-uk Kim	add	%rax,$acc0
781e71b7053SJung-uk Kim	adc	\$0,$acc1
782e71b7053SJung-uk Kim	adc	\$0,$acc2
783e71b7053SJung-uk Kim	mov	$acc1,8*1(%rdi)
784e71b7053SJung-uk Kim	adc	\$0,$acc3
785e71b7053SJung-uk Kim	mov	$acc2,8*2(%rdi)
786e71b7053SJung-uk Kim	sbb	%rax,%rax		# cf -> mask
787e71b7053SJung-uk Kim	mov	$acc3,8*3(%rdi)
788e71b7053SJung-uk Kim	and	\$38,%rax
789e71b7053SJung-uk Kim
790e71b7053SJung-uk Kim	add	%rax,$acc0
791e71b7053SJung-uk Kim	mov	$acc0,8*0(%rdi)
792e71b7053SJung-uk Kim
793e71b7053SJung-uk Kim.Lfe64_add_epilogue:
794e71b7053SJung-uk Kim	ret
79517f01e99SJung-uk Kim.cfi_endproc
796e71b7053SJung-uk Kim.size	x25519_fe64_add,.-x25519_fe64_add
797e71b7053SJung-uk Kim
798e71b7053SJung-uk Kim.globl	x25519_fe64_sub
799e71b7053SJung-uk Kim.type	x25519_fe64_sub,\@function,3
800e71b7053SJung-uk Kim.align	32
801e71b7053SJung-uk Kimx25519_fe64_sub:
802e71b7053SJung-uk Kim.Lfe64_sub_body:
80317f01e99SJung-uk Kim.cfi_startproc
804e71b7053SJung-uk Kim	mov	8*0(%rsi),$acc0
805e71b7053SJung-uk Kim	mov	8*1(%rsi),$acc1
806e71b7053SJung-uk Kim	mov	8*2(%rsi),$acc2
807e71b7053SJung-uk Kim	mov	8*3(%rsi),$acc3
808e71b7053SJung-uk Kim
809e71b7053SJung-uk Kim	sub	8*0(%rdx),$acc0
810e71b7053SJung-uk Kim	sbb	8*1(%rdx),$acc1
811e71b7053SJung-uk Kim	sbb	8*2(%rdx),$acc2
812e71b7053SJung-uk Kim	sbb	8*3(%rdx),$acc3
813e71b7053SJung-uk Kim
814e71b7053SJung-uk Kim	sbb	%rax,%rax		# cf -> mask
815e71b7053SJung-uk Kim	and	\$38,%rax
816e71b7053SJung-uk Kim
817e71b7053SJung-uk Kim	sub	%rax,$acc0
818e71b7053SJung-uk Kim	sbb	\$0,$acc1
819e71b7053SJung-uk Kim	sbb	\$0,$acc2
820e71b7053SJung-uk Kim	mov	$acc1,8*1(%rdi)
821e71b7053SJung-uk Kim	sbb	\$0,$acc3
822e71b7053SJung-uk Kim	mov	$acc2,8*2(%rdi)
823e71b7053SJung-uk Kim	sbb	%rax,%rax		# cf -> mask
824e71b7053SJung-uk Kim	mov	$acc3,8*3(%rdi)
825e71b7053SJung-uk Kim	and	\$38,%rax
826e71b7053SJung-uk Kim
827e71b7053SJung-uk Kim	sub	%rax,$acc0
828e71b7053SJung-uk Kim	mov	$acc0,8*0(%rdi)
829e71b7053SJung-uk Kim
830e71b7053SJung-uk Kim.Lfe64_sub_epilogue:
831e71b7053SJung-uk Kim	ret
83217f01e99SJung-uk Kim.cfi_endproc
833e71b7053SJung-uk Kim.size	x25519_fe64_sub,.-x25519_fe64_sub
834e71b7053SJung-uk Kim
835e71b7053SJung-uk Kim.globl	x25519_fe64_tobytes
836e71b7053SJung-uk Kim.type	x25519_fe64_tobytes,\@function,2
837e71b7053SJung-uk Kim.align	32
838e71b7053SJung-uk Kimx25519_fe64_tobytes:
839e71b7053SJung-uk Kim.Lfe64_to_body:
84017f01e99SJung-uk Kim.cfi_startproc
841e71b7053SJung-uk Kim	mov	8*0(%rsi),$acc0
842e71b7053SJung-uk Kim	mov	8*1(%rsi),$acc1
843e71b7053SJung-uk Kim	mov	8*2(%rsi),$acc2
844e71b7053SJung-uk Kim	mov	8*3(%rsi),$acc3
845e71b7053SJung-uk Kim
846e71b7053SJung-uk Kim	################################# reduction modulo 2^255-19
847e71b7053SJung-uk Kim	lea	($acc3,$acc3),%rax
848e71b7053SJung-uk Kim	sar	\$63,$acc3		# most significant bit -> mask
849e71b7053SJung-uk Kim	shr	\$1,%rax		# most significant bit cleared
850e71b7053SJung-uk Kim	and	\$19,$acc3
851e71b7053SJung-uk Kim	add	\$19,$acc3		# compare to modulus in the same go
852e71b7053SJung-uk Kim
853e71b7053SJung-uk Kim	add	$acc3,$acc0
854e71b7053SJung-uk Kim	adc	\$0,$acc1
855e71b7053SJung-uk Kim	adc	\$0,$acc2
856e71b7053SJung-uk Kim	adc	\$0,%rax
857e71b7053SJung-uk Kim
858e71b7053SJung-uk Kim	lea	(%rax,%rax),$acc3
859e71b7053SJung-uk Kim	sar	\$63,%rax		# most significant bit -> mask
860e71b7053SJung-uk Kim	shr	\$1,$acc3		# most significant bit cleared
861e71b7053SJung-uk Kim	not	%rax
862e71b7053SJung-uk Kim	and	\$19,%rax
863e71b7053SJung-uk Kim
864e71b7053SJung-uk Kim	sub	%rax,$acc0
865e71b7053SJung-uk Kim	sbb	\$0,$acc1
866e71b7053SJung-uk Kim	sbb	\$0,$acc2
867e71b7053SJung-uk Kim	sbb	\$0,$acc3
868e71b7053SJung-uk Kim
869e71b7053SJung-uk Kim	mov	$acc0,8*0(%rdi)
870e71b7053SJung-uk Kim	mov	$acc1,8*1(%rdi)
871e71b7053SJung-uk Kim	mov	$acc2,8*2(%rdi)
872e71b7053SJung-uk Kim	mov	$acc3,8*3(%rdi)
873e71b7053SJung-uk Kim
874e71b7053SJung-uk Kim.Lfe64_to_epilogue:
875e71b7053SJung-uk Kim	ret
87617f01e99SJung-uk Kim.cfi_endproc
877e71b7053SJung-uk Kim.size	x25519_fe64_tobytes,.-x25519_fe64_tobytes
878e71b7053SJung-uk Kim___
879e71b7053SJung-uk Kim} else {
880e71b7053SJung-uk Kim$code.=<<___;
881e71b7053SJung-uk Kim.globl	x25519_fe64_eligible
882e71b7053SJung-uk Kim.type	x25519_fe64_eligible,\@abi-omnipotent
883e71b7053SJung-uk Kim.align	32
884e71b7053SJung-uk Kimx25519_fe64_eligible:
88517f01e99SJung-uk Kim.cfi_startproc
886e71b7053SJung-uk Kim	xor	%eax,%eax
887e71b7053SJung-uk Kim	ret
88817f01e99SJung-uk Kim.cfi_endproc
889e71b7053SJung-uk Kim.size	x25519_fe64_eligible,.-x25519_fe64_eligible
890e71b7053SJung-uk Kim
891e71b7053SJung-uk Kim.globl	x25519_fe64_mul
892e71b7053SJung-uk Kim.type	x25519_fe64_mul,\@abi-omnipotent
893e71b7053SJung-uk Kim.globl	x25519_fe64_sqr
894e71b7053SJung-uk Kim.globl	x25519_fe64_mul121666
895e71b7053SJung-uk Kim.globl	x25519_fe64_add
896e71b7053SJung-uk Kim.globl	x25519_fe64_sub
897e71b7053SJung-uk Kim.globl	x25519_fe64_tobytes
898e71b7053SJung-uk Kimx25519_fe64_mul:
899e71b7053SJung-uk Kimx25519_fe64_sqr:
900e71b7053SJung-uk Kimx25519_fe64_mul121666:
901e71b7053SJung-uk Kimx25519_fe64_add:
902e71b7053SJung-uk Kimx25519_fe64_sub:
903e71b7053SJung-uk Kimx25519_fe64_tobytes:
90417f01e99SJung-uk Kim.cfi_startproc
905e71b7053SJung-uk Kim	.byte	0x0f,0x0b	# ud2
906e71b7053SJung-uk Kim	ret
90717f01e99SJung-uk Kim.cfi_endproc
908e71b7053SJung-uk Kim.size	x25519_fe64_mul,.-x25519_fe64_mul
909e71b7053SJung-uk Kim___
910e71b7053SJung-uk Kim}
911e71b7053SJung-uk Kim$code.=<<___;
912e71b7053SJung-uk Kim.asciz	"X25519 primitives for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
913e71b7053SJung-uk Kim___
914e71b7053SJung-uk Kim
915e71b7053SJung-uk Kim# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
916e71b7053SJung-uk Kim#		CONTEXT *context,DISPATCHER_CONTEXT *disp)
917e71b7053SJung-uk Kimif ($win64) {
918e71b7053SJung-uk Kim$rec="%rcx";
919e71b7053SJung-uk Kim$frame="%rdx";
920e71b7053SJung-uk Kim$context="%r8";
921e71b7053SJung-uk Kim$disp="%r9";
922e71b7053SJung-uk Kim
923e71b7053SJung-uk Kim$code.=<<___;
924e71b7053SJung-uk Kim.extern	__imp_RtlVirtualUnwind
925e71b7053SJung-uk Kim
926e71b7053SJung-uk Kim.type	short_handler,\@abi-omnipotent
927e71b7053SJung-uk Kim.align	16
928e71b7053SJung-uk Kimshort_handler:
929e71b7053SJung-uk Kim	push	%rsi
930e71b7053SJung-uk Kim	push	%rdi
931e71b7053SJung-uk Kim	push	%rbx
932e71b7053SJung-uk Kim	push	%rbp
933e71b7053SJung-uk Kim	push	%r12
934e71b7053SJung-uk Kim	push	%r13
935e71b7053SJung-uk Kim	push	%r14
936e71b7053SJung-uk Kim	push	%r15
937e71b7053SJung-uk Kim	pushfq
938e71b7053SJung-uk Kim	sub	\$64,%rsp
939e71b7053SJung-uk Kim
940e71b7053SJung-uk Kim	mov	120($context),%rax	# pull context->Rax
941e71b7053SJung-uk Kim	mov	248($context),%rbx	# pull context->Rip
942e71b7053SJung-uk Kim
943e71b7053SJung-uk Kim	mov	8($disp),%rsi		# disp->ImageBase
944e71b7053SJung-uk Kim	mov	56($disp),%r11		# disp->HandlerData
945e71b7053SJung-uk Kim
946e71b7053SJung-uk Kim	mov	0(%r11),%r10d		# HandlerData[0]
947e71b7053SJung-uk Kim	lea	(%rsi,%r10),%r10	# end of prologue label
948e71b7053SJung-uk Kim	cmp	%r10,%rbx		# context->Rip<end of prologue label
949e71b7053SJung-uk Kim	jb	.Lcommon_seh_tail
950e71b7053SJung-uk Kim
951e71b7053SJung-uk Kim	mov	152($context),%rax	# pull context->Rsp
952e71b7053SJung-uk Kim	jmp	.Lcommon_seh_tail
953e71b7053SJung-uk Kim.size	short_handler,.-short_handler
954e71b7053SJung-uk Kim
955e71b7053SJung-uk Kim.type	full_handler,\@abi-omnipotent
956e71b7053SJung-uk Kim.align	16
957e71b7053SJung-uk Kimfull_handler:
958e71b7053SJung-uk Kim	push	%rsi
959e71b7053SJung-uk Kim	push	%rdi
960e71b7053SJung-uk Kim	push	%rbx
961e71b7053SJung-uk Kim	push	%rbp
962e71b7053SJung-uk Kim	push	%r12
963e71b7053SJung-uk Kim	push	%r13
964e71b7053SJung-uk Kim	push	%r14
965e71b7053SJung-uk Kim	push	%r15
966e71b7053SJung-uk Kim	pushfq
967e71b7053SJung-uk Kim	sub	\$64,%rsp
968e71b7053SJung-uk Kim
969e71b7053SJung-uk Kim	mov	120($context),%rax	# pull context->Rax
970e71b7053SJung-uk Kim	mov	248($context),%rbx	# pull context->Rip
971e71b7053SJung-uk Kim
972e71b7053SJung-uk Kim	mov	8($disp),%rsi		# disp->ImageBase
973e71b7053SJung-uk Kim	mov	56($disp),%r11		# disp->HandlerData
974e71b7053SJung-uk Kim
975e71b7053SJung-uk Kim	mov	0(%r11),%r10d		# HandlerData[0]
976e71b7053SJung-uk Kim	lea	(%rsi,%r10),%r10	# end of prologue label
977e71b7053SJung-uk Kim	cmp	%r10,%rbx		# context->Rip<end of prologue label
978e71b7053SJung-uk Kim	jb	.Lcommon_seh_tail
979e71b7053SJung-uk Kim
980e71b7053SJung-uk Kim	mov	152($context),%rax	# pull context->Rsp
981e71b7053SJung-uk Kim
982e71b7053SJung-uk Kim	mov	4(%r11),%r10d		# HandlerData[1]
983e71b7053SJung-uk Kim	lea	(%rsi,%r10),%r10	# epilogue label
984e71b7053SJung-uk Kim	cmp	%r10,%rbx		# context->Rip>=epilogue label
985e71b7053SJung-uk Kim	jae	.Lcommon_seh_tail
986e71b7053SJung-uk Kim
987e71b7053SJung-uk Kim	mov	8(%r11),%r10d		# HandlerData[2]
988e71b7053SJung-uk Kim	lea	(%rax,%r10),%rax
989e71b7053SJung-uk Kim
990e71b7053SJung-uk Kim	mov	-8(%rax),%rbp
991e71b7053SJung-uk Kim	mov	-16(%rax),%rbx
992e71b7053SJung-uk Kim	mov	-24(%rax),%r12
993e71b7053SJung-uk Kim	mov	-32(%rax),%r13
994e71b7053SJung-uk Kim	mov	-40(%rax),%r14
995e71b7053SJung-uk Kim	mov	-48(%rax),%r15
996e71b7053SJung-uk Kim	mov	%rbx,144($context)	# restore context->Rbx
997e71b7053SJung-uk Kim	mov	%rbp,160($context)	# restore context->Rbp
998e71b7053SJung-uk Kim	mov	%r12,216($context)	# restore context->R12
999e71b7053SJung-uk Kim	mov	%r13,224($context)	# restore context->R13
1000e71b7053SJung-uk Kim	mov	%r14,232($context)	# restore context->R14
1001e71b7053SJung-uk Kim	mov	%r15,240($context)	# restore context->R15
1002e71b7053SJung-uk Kim
1003e71b7053SJung-uk Kim.Lcommon_seh_tail:
1004e71b7053SJung-uk Kim	mov	8(%rax),%rdi
1005e71b7053SJung-uk Kim	mov	16(%rax),%rsi
1006e71b7053SJung-uk Kim	mov	%rax,152($context)	# restore context->Rsp
1007e71b7053SJung-uk Kim	mov	%rsi,168($context)	# restore context->Rsi
1008e71b7053SJung-uk Kim	mov	%rdi,176($context)	# restore context->Rdi
1009e71b7053SJung-uk Kim
1010e71b7053SJung-uk Kim	mov	40($disp),%rdi		# disp->ContextRecord
1011e71b7053SJung-uk Kim	mov	$context,%rsi		# context
1012e71b7053SJung-uk Kim	mov	\$154,%ecx		# sizeof(CONTEXT)
1013e71b7053SJung-uk Kim	.long	0xa548f3fc		# cld; rep movsq
1014e71b7053SJung-uk Kim
1015e71b7053SJung-uk Kim	mov	$disp,%rsi
1016e71b7053SJung-uk Kim	xor	%rcx,%rcx		# arg1, UNW_FLAG_NHANDLER
1017e71b7053SJung-uk Kim	mov	8(%rsi),%rdx		# arg2, disp->ImageBase
1018e71b7053SJung-uk Kim	mov	0(%rsi),%r8		# arg3, disp->ControlPc
1019e71b7053SJung-uk Kim	mov	16(%rsi),%r9		# arg4, disp->FunctionEntry
1020e71b7053SJung-uk Kim	mov	40(%rsi),%r10		# disp->ContextRecord
1021e71b7053SJung-uk Kim	lea	56(%rsi),%r11		# &disp->HandlerData
1022e71b7053SJung-uk Kim	lea	24(%rsi),%r12		# &disp->EstablisherFrame
1023e71b7053SJung-uk Kim	mov	%r10,32(%rsp)		# arg5
1024e71b7053SJung-uk Kim	mov	%r11,40(%rsp)		# arg6
1025e71b7053SJung-uk Kim	mov	%r12,48(%rsp)		# arg7
1026e71b7053SJung-uk Kim	mov	%rcx,56(%rsp)		# arg8, (NULL)
1027e71b7053SJung-uk Kim	call	*__imp_RtlVirtualUnwind(%rip)
1028e71b7053SJung-uk Kim
1029e71b7053SJung-uk Kim	mov	\$1,%eax		# ExceptionContinueSearch
1030e71b7053SJung-uk Kim	add	\$64,%rsp
1031e71b7053SJung-uk Kim	popfq
1032e71b7053SJung-uk Kim	pop	%r15
1033e71b7053SJung-uk Kim	pop	%r14
1034e71b7053SJung-uk Kim	pop	%r13
1035e71b7053SJung-uk Kim	pop	%r12
1036e71b7053SJung-uk Kim	pop	%rbp
1037e71b7053SJung-uk Kim	pop	%rbx
1038e71b7053SJung-uk Kim	pop	%rdi
1039e71b7053SJung-uk Kim	pop	%rsi
1040e71b7053SJung-uk Kim	ret
1041e71b7053SJung-uk Kim.size	full_handler,.-full_handler
1042e71b7053SJung-uk Kim
1043e71b7053SJung-uk Kim.section	.pdata
1044e71b7053SJung-uk Kim.align	4
1045e71b7053SJung-uk Kim	.rva	.LSEH_begin_x25519_fe51_mul
1046e71b7053SJung-uk Kim	.rva	.LSEH_end_x25519_fe51_mul
1047e71b7053SJung-uk Kim	.rva	.LSEH_info_x25519_fe51_mul
1048e71b7053SJung-uk Kim
1049e71b7053SJung-uk Kim	.rva	.LSEH_begin_x25519_fe51_sqr
1050e71b7053SJung-uk Kim	.rva	.LSEH_end_x25519_fe51_sqr
1051e71b7053SJung-uk Kim	.rva	.LSEH_info_x25519_fe51_sqr
1052e71b7053SJung-uk Kim
1053e71b7053SJung-uk Kim	.rva	.LSEH_begin_x25519_fe51_mul121666
1054e71b7053SJung-uk Kim	.rva	.LSEH_end_x25519_fe51_mul121666
1055e71b7053SJung-uk Kim	.rva	.LSEH_info_x25519_fe51_mul121666
1056e71b7053SJung-uk Kim___
1057e71b7053SJung-uk Kim$code.=<<___	if ($addx);
1058e71b7053SJung-uk Kim	.rva	.LSEH_begin_x25519_fe64_mul
1059e71b7053SJung-uk Kim	.rva	.LSEH_end_x25519_fe64_mul
1060e71b7053SJung-uk Kim	.rva	.LSEH_info_x25519_fe64_mul
1061e71b7053SJung-uk Kim
1062e71b7053SJung-uk Kim	.rva	.LSEH_begin_x25519_fe64_sqr
1063e71b7053SJung-uk Kim	.rva	.LSEH_end_x25519_fe64_sqr
1064e71b7053SJung-uk Kim	.rva	.LSEH_info_x25519_fe64_sqr
1065e71b7053SJung-uk Kim
1066e71b7053SJung-uk Kim	.rva	.LSEH_begin_x25519_fe64_mul121666
1067e71b7053SJung-uk Kim	.rva	.LSEH_end_x25519_fe64_mul121666
1068e71b7053SJung-uk Kim	.rva	.LSEH_info_x25519_fe64_mul121666
1069e71b7053SJung-uk Kim
1070e71b7053SJung-uk Kim	.rva	.LSEH_begin_x25519_fe64_add
1071e71b7053SJung-uk Kim	.rva	.LSEH_end_x25519_fe64_add
1072e71b7053SJung-uk Kim	.rva	.LSEH_info_x25519_fe64_add
1073e71b7053SJung-uk Kim
1074e71b7053SJung-uk Kim	.rva	.LSEH_begin_x25519_fe64_sub
1075e71b7053SJung-uk Kim	.rva	.LSEH_end_x25519_fe64_sub
1076e71b7053SJung-uk Kim	.rva	.LSEH_info_x25519_fe64_sub
1077e71b7053SJung-uk Kim
1078e71b7053SJung-uk Kim	.rva	.LSEH_begin_x25519_fe64_tobytes
1079e71b7053SJung-uk Kim	.rva	.LSEH_end_x25519_fe64_tobytes
1080e71b7053SJung-uk Kim	.rva	.LSEH_info_x25519_fe64_tobytes
1081e71b7053SJung-uk Kim___
1082e71b7053SJung-uk Kim$code.=<<___;
1083e71b7053SJung-uk Kim.section	.xdata
1084e71b7053SJung-uk Kim.align	8
1085e71b7053SJung-uk Kim.LSEH_info_x25519_fe51_mul:
1086e71b7053SJung-uk Kim	.byte	9,0,0,0
1087e71b7053SJung-uk Kim	.rva	full_handler
1088e71b7053SJung-uk Kim	.rva	.Lfe51_mul_body,.Lfe51_mul_epilogue	# HandlerData[]
1089e71b7053SJung-uk Kim	.long	88,0
1090e71b7053SJung-uk Kim.LSEH_info_x25519_fe51_sqr:
1091e71b7053SJung-uk Kim	.byte	9,0,0,0
1092e71b7053SJung-uk Kim	.rva	full_handler
1093e71b7053SJung-uk Kim	.rva	.Lfe51_sqr_body,.Lfe51_sqr_epilogue	# HandlerData[]
1094e71b7053SJung-uk Kim	.long	88,0
1095e71b7053SJung-uk Kim.LSEH_info_x25519_fe51_mul121666:
1096e71b7053SJung-uk Kim	.byte	9,0,0,0
1097e71b7053SJung-uk Kim	.rva	full_handler
1098e71b7053SJung-uk Kim	.rva	.Lfe51_mul121666_body,.Lfe51_mul121666_epilogue	# HandlerData[]
1099e71b7053SJung-uk Kim	.long	88,0
1100e71b7053SJung-uk Kim___
1101e71b7053SJung-uk Kim$code.=<<___	if ($addx);
1102e71b7053SJung-uk Kim.LSEH_info_x25519_fe64_mul:
1103e71b7053SJung-uk Kim	.byte	9,0,0,0
1104e71b7053SJung-uk Kim	.rva	full_handler
1105e71b7053SJung-uk Kim	.rva	.Lfe64_mul_body,.Lfe64_mul_epilogue	# HandlerData[]
1106e71b7053SJung-uk Kim	.long	72,0
1107e71b7053SJung-uk Kim.LSEH_info_x25519_fe64_sqr:
1108e71b7053SJung-uk Kim	.byte	9,0,0,0
1109e71b7053SJung-uk Kim	.rva	full_handler
1110e71b7053SJung-uk Kim	.rva	.Lfe64_sqr_body,.Lfe64_sqr_epilogue	# HandlerData[]
1111e71b7053SJung-uk Kim	.long	72,0
1112e71b7053SJung-uk Kim.LSEH_info_x25519_fe64_mul121666:
1113e71b7053SJung-uk Kim	.byte	9,0,0,0
1114e71b7053SJung-uk Kim	.rva	short_handler
1115e71b7053SJung-uk Kim	.rva	.Lfe64_mul121666_body,.Lfe64_mul121666_epilogue	# HandlerData[]
1116e71b7053SJung-uk Kim.LSEH_info_x25519_fe64_add:
1117e71b7053SJung-uk Kim	.byte	9,0,0,0
1118e71b7053SJung-uk Kim	.rva	short_handler
1119e71b7053SJung-uk Kim	.rva	.Lfe64_add_body,.Lfe64_add_epilogue	# HandlerData[]
1120e71b7053SJung-uk Kim.LSEH_info_x25519_fe64_sub:
1121e71b7053SJung-uk Kim	.byte	9,0,0,0
1122e71b7053SJung-uk Kim	.rva	short_handler
1123e71b7053SJung-uk Kim	.rva	.Lfe64_sub_body,.Lfe64_sub_epilogue	# HandlerData[]
1124e71b7053SJung-uk Kim.LSEH_info_x25519_fe64_tobytes:
1125e71b7053SJung-uk Kim	.byte	9,0,0,0
1126e71b7053SJung-uk Kim	.rva	short_handler
1127e71b7053SJung-uk Kim	.rva	.Lfe64_to_body,.Lfe64_to_epilogue	# HandlerData[]
1128e71b7053SJung-uk Kim___
1129e71b7053SJung-uk Kim}
1130e71b7053SJung-uk Kim
1131e71b7053SJung-uk Kim$code =~ s/\`([^\`]*)\`/eval $1/gem;
1132e71b7053SJung-uk Kimprint $code;
113317f01e99SJung-uk Kimclose STDOUT or die "error closing STDOUT: $!";
1134