1e1051a39Sopenharmony_ci#! /usr/bin/env perl
2e1051a39Sopenharmony_ci# Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci#
4e1051a39Sopenharmony_ci# Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci# this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci# in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci# https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci
9e1051a39Sopenharmony_ci#
10e1051a39Sopenharmony_ci# ====================================================================
11e1051a39Sopenharmony_ci# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
12e1051a39Sopenharmony_ci# project. The module is, however, dual licensed under OpenSSL and
13e1051a39Sopenharmony_ci# CRYPTOGAMS licenses depending on where you obtain it. For further
14e1051a39Sopenharmony_ci# details see http://www.openssl.org/~appro/cryptogams/.
15e1051a39Sopenharmony_ci# ====================================================================
16e1051a39Sopenharmony_ci#
17e1051a39Sopenharmony_ci# May 2011
18e1051a39Sopenharmony_ci#
19e1051a39Sopenharmony_ci# The module implements bn_GF2m_mul_2x2 polynomial multiplication used
20e1051a39Sopenharmony_ci# in bn_gf2m.c. It's kind of low-hanging mechanical port from C for
21e1051a39Sopenharmony_ci# the time being... Except that it has three code paths: pure integer
22e1051a39Sopenharmony_ci# code suitable for any x86 CPU, MMX code suitable for PIII and later
23e1051a39Sopenharmony_ci# and PCLMULQDQ suitable for Westmere and later. Improvement varies
24e1051a39Sopenharmony_ci# from one benchmark and µ-arch to another. Below are interval values
25e1051a39Sopenharmony_ci# for 163- and 571-bit ECDH benchmarks relative to compiler-generated
26e1051a39Sopenharmony_ci# code:
27e1051a39Sopenharmony_ci#
28e1051a39Sopenharmony_ci# PIII		16%-30%
29e1051a39Sopenharmony_ci# P4		12%-12%
30e1051a39Sopenharmony_ci# Opteron	18%-40%
31e1051a39Sopenharmony_ci# Core2		19%-44%
32e1051a39Sopenharmony_ci# Atom		38%-64%
33e1051a39Sopenharmony_ci# Westmere	53%-121%(PCLMULQDQ)/20%-32%(MMX)
34e1051a39Sopenharmony_ci# Sandy Bridge	72%-127%(PCLMULQDQ)/27%-23%(MMX)
35e1051a39Sopenharmony_ci#
36e1051a39Sopenharmony_ci# Note that above improvement coefficients are not coefficients for
37e1051a39Sopenharmony_ci# bn_GF2m_mul_2x2 itself. For example 120% ECDH improvement is result
38e1051a39Sopenharmony_ci# of bn_GF2m_mul_2x2 being >4x faster. As it gets faster, benchmark
39e1051a39Sopenharmony_ci# is more and more dominated by other subroutines, most notably by
40e1051a39Sopenharmony_ci# BN_GF2m_mod[_mul]_arr...
41e1051a39Sopenharmony_ci
42e1051a39Sopenharmony_ci$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
43e1051a39Sopenharmony_cipush(@INC,"${dir}","${dir}../../perlasm");
44e1051a39Sopenharmony_cirequire "x86asm.pl";
45e1051a39Sopenharmony_ci
46e1051a39Sopenharmony_ci$output = pop and open STDOUT,">$output";
47e1051a39Sopenharmony_ci
48e1051a39Sopenharmony_ci&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386");
49e1051a39Sopenharmony_ci
50e1051a39Sopenharmony_ci$sse2=0;
51e1051a39Sopenharmony_cifor (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
52e1051a39Sopenharmony_ci
53e1051a39Sopenharmony_ci&external_label("OPENSSL_ia32cap_P") if ($sse2);
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_ci$a="eax";
56e1051a39Sopenharmony_ci$b="ebx";
57e1051a39Sopenharmony_ci($a1,$a2,$a4)=("ecx","edx","ebp");
58e1051a39Sopenharmony_ci
59e1051a39Sopenharmony_ci$R="mm0";
60e1051a39Sopenharmony_ci@T=("mm1","mm2");
61e1051a39Sopenharmony_ci($A,$B,$B30,$B31)=("mm2","mm3","mm4","mm5");
62e1051a39Sopenharmony_ci@i=("esi","edi");
63e1051a39Sopenharmony_ci
64e1051a39Sopenharmony_ci					if (!$x86only) {
65e1051a39Sopenharmony_ci&function_begin_B("_mul_1x1_mmx");
66e1051a39Sopenharmony_ci	&sub	("esp",32+4);
67e1051a39Sopenharmony_ci	 &mov	($a1,$a);
68e1051a39Sopenharmony_ci	 &lea	($a2,&DWP(0,$a,$a));
69e1051a39Sopenharmony_ci	 &and	($a1,0x3fffffff);
70e1051a39Sopenharmony_ci	 &lea	($a4,&DWP(0,$a2,$a2));
71e1051a39Sopenharmony_ci	 &mov	(&DWP(0*4,"esp"),0);
72e1051a39Sopenharmony_ci	 &and	($a2,0x7fffffff);
73e1051a39Sopenharmony_ci	&movd	($A,$a);
74e1051a39Sopenharmony_ci	&movd	($B,$b);
75e1051a39Sopenharmony_ci	 &mov	(&DWP(1*4,"esp"),$a1);	# a1
76e1051a39Sopenharmony_ci	 &xor	($a1,$a2);		# a1^a2
77e1051a39Sopenharmony_ci	&pxor	($B31,$B31);
78e1051a39Sopenharmony_ci	&pxor	($B30,$B30);
79e1051a39Sopenharmony_ci	 &mov	(&DWP(2*4,"esp"),$a2);	# a2
80e1051a39Sopenharmony_ci	 &xor	($a2,$a4);		# a2^a4
81e1051a39Sopenharmony_ci	 &mov	(&DWP(3*4,"esp"),$a1);	# a1^a2
82e1051a39Sopenharmony_ci	&pcmpgtd($B31,$A);		# broadcast 31st bit
83e1051a39Sopenharmony_ci	&paddd	($A,$A);		# $A<<=1
84e1051a39Sopenharmony_ci	 &xor	($a1,$a2);		# a1^a4=a1^a2^a2^a4
85e1051a39Sopenharmony_ci	 &mov	(&DWP(4*4,"esp"),$a4);	# a4
86e1051a39Sopenharmony_ci	 &xor	($a4,$a2);		# a2=a4^a2^a4
87e1051a39Sopenharmony_ci	&pand	($B31,$B);
88e1051a39Sopenharmony_ci	&pcmpgtd($B30,$A);		# broadcast 30th bit
89e1051a39Sopenharmony_ci	 &mov	(&DWP(5*4,"esp"),$a1);	# a1^a4
90e1051a39Sopenharmony_ci	 &xor	($a4,$a1);		# a1^a2^a4
91e1051a39Sopenharmony_ci	&psllq	($B31,31);
92e1051a39Sopenharmony_ci	&pand	($B30,$B);
93e1051a39Sopenharmony_ci	 &mov	(&DWP(6*4,"esp"),$a2);	# a2^a4
94e1051a39Sopenharmony_ci	&mov	(@i[0],0x7);
95e1051a39Sopenharmony_ci	 &mov	(&DWP(7*4,"esp"),$a4);	# a1^a2^a4
96e1051a39Sopenharmony_ci	 &mov	($a4,@i[0]);
97e1051a39Sopenharmony_ci	&and	(@i[0],$b);
98e1051a39Sopenharmony_ci	&shr	($b,3);
99e1051a39Sopenharmony_ci	&mov	(@i[1],$a4);
100e1051a39Sopenharmony_ci	&psllq	($B30,30);
101e1051a39Sopenharmony_ci	&and	(@i[1],$b);
102e1051a39Sopenharmony_ci	&shr	($b,3);
103e1051a39Sopenharmony_ci	&movd	($R,&DWP(0,"esp",@i[0],4));
104e1051a39Sopenharmony_ci	&mov	(@i[0],$a4);
105e1051a39Sopenharmony_ci	&and	(@i[0],$b);
106e1051a39Sopenharmony_ci	&shr	($b,3);
107e1051a39Sopenharmony_ci	for($n=1;$n<9;$n++) {
108e1051a39Sopenharmony_ci		&movd	(@T[1],&DWP(0,"esp",@i[1],4));
109e1051a39Sopenharmony_ci		&mov	(@i[1],$a4);
110e1051a39Sopenharmony_ci		&psllq	(@T[1],3*$n);
111e1051a39Sopenharmony_ci		&and	(@i[1],$b);
112e1051a39Sopenharmony_ci		&shr	($b,3);
113e1051a39Sopenharmony_ci		&pxor	($R,@T[1]);
114e1051a39Sopenharmony_ci
115e1051a39Sopenharmony_ci		push(@i,shift(@i)); push(@T,shift(@T));
116e1051a39Sopenharmony_ci	}
117e1051a39Sopenharmony_ci	&movd	(@T[1],&DWP(0,"esp",@i[1],4));
118e1051a39Sopenharmony_ci	&pxor	($R,$B30);
119e1051a39Sopenharmony_ci	&psllq	(@T[1],3*$n++);
120e1051a39Sopenharmony_ci	&pxor	($R,@T[1]);
121e1051a39Sopenharmony_ci
122e1051a39Sopenharmony_ci	&movd	(@T[0],&DWP(0,"esp",@i[0],4));
123e1051a39Sopenharmony_ci	&pxor	($R,$B31);
124e1051a39Sopenharmony_ci	&psllq	(@T[0],3*$n);
125e1051a39Sopenharmony_ci	&add	("esp",32+4);
126e1051a39Sopenharmony_ci	&pxor	($R,@T[0]);
127e1051a39Sopenharmony_ci	&ret	();
128e1051a39Sopenharmony_ci&function_end_B("_mul_1x1_mmx");
129e1051a39Sopenharmony_ci					}
130e1051a39Sopenharmony_ci
131e1051a39Sopenharmony_ci($lo,$hi)=("eax","edx");
132e1051a39Sopenharmony_ci@T=("ecx","ebp");
133e1051a39Sopenharmony_ci
134e1051a39Sopenharmony_ci&function_begin_B("_mul_1x1_ialu");
135e1051a39Sopenharmony_ci	&sub	("esp",32+4);
136e1051a39Sopenharmony_ci	 &mov	($a1,$a);
137e1051a39Sopenharmony_ci	 &lea	($a2,&DWP(0,$a,$a));
138e1051a39Sopenharmony_ci	 &lea	($a4,&DWP(0,"",$a,4));
139e1051a39Sopenharmony_ci	 &and	($a1,0x3fffffff);
140e1051a39Sopenharmony_ci	&lea	(@i[1],&DWP(0,$lo,$lo));
141e1051a39Sopenharmony_ci	&sar	($lo,31);		# broadcast 31st bit
142e1051a39Sopenharmony_ci	 &mov	(&DWP(0*4,"esp"),0);
143e1051a39Sopenharmony_ci	 &and	($a2,0x7fffffff);
144e1051a39Sopenharmony_ci	 &mov	(&DWP(1*4,"esp"),$a1);	# a1
145e1051a39Sopenharmony_ci	 &xor	($a1,$a2);		# a1^a2
146e1051a39Sopenharmony_ci	 &mov	(&DWP(2*4,"esp"),$a2);	# a2
147e1051a39Sopenharmony_ci	 &xor	($a2,$a4);		# a2^a4
148e1051a39Sopenharmony_ci	 &mov	(&DWP(3*4,"esp"),$a1);	# a1^a2
149e1051a39Sopenharmony_ci	 &xor	($a1,$a2);		# a1^a4=a1^a2^a2^a4
150e1051a39Sopenharmony_ci	 &mov	(&DWP(4*4,"esp"),$a4);	# a4
151e1051a39Sopenharmony_ci	 &xor	($a4,$a2);		# a2=a4^a2^a4
152e1051a39Sopenharmony_ci	 &mov	(&DWP(5*4,"esp"),$a1);	# a1^a4
153e1051a39Sopenharmony_ci	 &xor	($a4,$a1);		# a1^a2^a4
154e1051a39Sopenharmony_ci	&sar	(@i[1],31);		# broadcast 30th bit
155e1051a39Sopenharmony_ci	&and	($lo,$b);
156e1051a39Sopenharmony_ci	 &mov	(&DWP(6*4,"esp"),$a2);	# a2^a4
157e1051a39Sopenharmony_ci	&and	(@i[1],$b);
158e1051a39Sopenharmony_ci	 &mov	(&DWP(7*4,"esp"),$a4);	# a1^a2^a4
159e1051a39Sopenharmony_ci	&mov	($hi,$lo);
160e1051a39Sopenharmony_ci	&shl	($lo,31);
161e1051a39Sopenharmony_ci	&mov	(@T[0],@i[1]);
162e1051a39Sopenharmony_ci	&shr	($hi,1);
163e1051a39Sopenharmony_ci
164e1051a39Sopenharmony_ci	 &mov	(@i[0],0x7);
165e1051a39Sopenharmony_ci	&shl	(@i[1],30);
166e1051a39Sopenharmony_ci	 &and	(@i[0],$b);
167e1051a39Sopenharmony_ci	&shr	(@T[0],2);
168e1051a39Sopenharmony_ci	&xor	($lo,@i[1]);
169e1051a39Sopenharmony_ci
170e1051a39Sopenharmony_ci	&shr	($b,3);
171e1051a39Sopenharmony_ci	&mov	(@i[1],0x7);		# 5-byte instruction!?
172e1051a39Sopenharmony_ci	&and	(@i[1],$b);
173e1051a39Sopenharmony_ci	&shr	($b,3);
174e1051a39Sopenharmony_ci	 &xor	($hi,@T[0]);
175e1051a39Sopenharmony_ci	&xor	($lo,&DWP(0,"esp",@i[0],4));
176e1051a39Sopenharmony_ci	&mov	(@i[0],0x7);
177e1051a39Sopenharmony_ci	&and	(@i[0],$b);
178e1051a39Sopenharmony_ci	&shr	($b,3);
179e1051a39Sopenharmony_ci	for($n=1;$n<9;$n++) {
180e1051a39Sopenharmony_ci		&mov	(@T[1],&DWP(0,"esp",@i[1],4));
181e1051a39Sopenharmony_ci		&mov	(@i[1],0x7);
182e1051a39Sopenharmony_ci		&mov	(@T[0],@T[1]);
183e1051a39Sopenharmony_ci		&shl	(@T[1],3*$n);
184e1051a39Sopenharmony_ci		&and	(@i[1],$b);
185e1051a39Sopenharmony_ci		&shr	(@T[0],32-3*$n);
186e1051a39Sopenharmony_ci		&xor	($lo,@T[1]);
187e1051a39Sopenharmony_ci		&shr	($b,3);
188e1051a39Sopenharmony_ci		&xor	($hi,@T[0]);
189e1051a39Sopenharmony_ci
190e1051a39Sopenharmony_ci		push(@i,shift(@i)); push(@T,shift(@T));
191e1051a39Sopenharmony_ci	}
192e1051a39Sopenharmony_ci	&mov	(@T[1],&DWP(0,"esp",@i[1],4));
193e1051a39Sopenharmony_ci	&mov	(@T[0],@T[1]);
194e1051a39Sopenharmony_ci	&shl	(@T[1],3*$n);
195e1051a39Sopenharmony_ci	&mov	(@i[1],&DWP(0,"esp",@i[0],4));
196e1051a39Sopenharmony_ci	&shr	(@T[0],32-3*$n);	$n++;
197e1051a39Sopenharmony_ci	&mov	(@i[0],@i[1]);
198e1051a39Sopenharmony_ci	&xor	($lo,@T[1]);
199e1051a39Sopenharmony_ci	&shl	(@i[1],3*$n);
200e1051a39Sopenharmony_ci	&xor	($hi,@T[0]);
201e1051a39Sopenharmony_ci	&shr	(@i[0],32-3*$n);
202e1051a39Sopenharmony_ci	&xor	($lo,@i[1]);
203e1051a39Sopenharmony_ci	&xor	($hi,@i[0]);
204e1051a39Sopenharmony_ci
205e1051a39Sopenharmony_ci	&add	("esp",32+4);
206e1051a39Sopenharmony_ci	&ret	();
207e1051a39Sopenharmony_ci&function_end_B("_mul_1x1_ialu");
208e1051a39Sopenharmony_ci
209e1051a39Sopenharmony_ci# void bn_GF2m_mul_2x2(BN_ULONG *r, BN_ULONG a1, BN_ULONG a0, BN_ULONG b1, BN_ULONG b0);
210e1051a39Sopenharmony_ci&function_begin_B("bn_GF2m_mul_2x2");
211e1051a39Sopenharmony_ciif (!$x86only) {
212e1051a39Sopenharmony_ci	&picmeup("edx","OPENSSL_ia32cap_P");
213e1051a39Sopenharmony_ci	&mov	("eax",&DWP(0,"edx"));
214e1051a39Sopenharmony_ci	&mov	("edx",&DWP(4,"edx"));
215e1051a39Sopenharmony_ci	&test	("eax",1<<23);		# check MMX bit
216e1051a39Sopenharmony_ci	&jz	(&label("ialu"));
217e1051a39Sopenharmony_ciif ($sse2) {
218e1051a39Sopenharmony_ci	&test	("eax",1<<24);		# check FXSR bit
219e1051a39Sopenharmony_ci	&jz	(&label("mmx"));
220e1051a39Sopenharmony_ci	&test	("edx",1<<1);		# check PCLMULQDQ bit
221e1051a39Sopenharmony_ci	&jz	(&label("mmx"));
222e1051a39Sopenharmony_ci
223e1051a39Sopenharmony_ci	&movups		("xmm0",&QWP(8,"esp"));
224e1051a39Sopenharmony_ci	&shufps		("xmm0","xmm0",0b10110001);
225e1051a39Sopenharmony_ci	&pclmulqdq	("xmm0","xmm0",1);
226e1051a39Sopenharmony_ci	&mov		("eax",&DWP(4,"esp"));
227e1051a39Sopenharmony_ci	&movups		(&QWP(0,"eax"),"xmm0");
228e1051a39Sopenharmony_ci	&ret	();
229e1051a39Sopenharmony_ci
230e1051a39Sopenharmony_ci&set_label("mmx",16);
231e1051a39Sopenharmony_ci}
232e1051a39Sopenharmony_ci	&push	("ebp");
233e1051a39Sopenharmony_ci	&push	("ebx");
234e1051a39Sopenharmony_ci	&push	("esi");
235e1051a39Sopenharmony_ci	&push	("edi");
236e1051a39Sopenharmony_ci	&mov	($a,&wparam(1));
237e1051a39Sopenharmony_ci	&mov	($b,&wparam(3));
238e1051a39Sopenharmony_ci	&call	("_mul_1x1_mmx");	# a1·b1
239e1051a39Sopenharmony_ci	&movq	("mm7",$R);
240e1051a39Sopenharmony_ci
241e1051a39Sopenharmony_ci	&mov	($a,&wparam(2));
242e1051a39Sopenharmony_ci	&mov	($b,&wparam(4));
243e1051a39Sopenharmony_ci	&call	("_mul_1x1_mmx");	# a0·b0
244e1051a39Sopenharmony_ci	&movq	("mm6",$R);
245e1051a39Sopenharmony_ci
246e1051a39Sopenharmony_ci	&mov	($a,&wparam(1));
247e1051a39Sopenharmony_ci	&mov	($b,&wparam(3));
248e1051a39Sopenharmony_ci	&xor	($a,&wparam(2));
249e1051a39Sopenharmony_ci	&xor	($b,&wparam(4));
250e1051a39Sopenharmony_ci	&call	("_mul_1x1_mmx");	# (a0+a1)·(b0+b1)
251e1051a39Sopenharmony_ci	&pxor	($R,"mm7");
252e1051a39Sopenharmony_ci	&mov	($a,&wparam(0));
253e1051a39Sopenharmony_ci	&pxor	($R,"mm6");		# (a0+a1)·(b0+b1)-a1·b1-a0·b0
254e1051a39Sopenharmony_ci
255e1051a39Sopenharmony_ci	&movq	($A,$R);
256e1051a39Sopenharmony_ci	&psllq	($R,32);
257e1051a39Sopenharmony_ci	&pop	("edi");
258e1051a39Sopenharmony_ci	&psrlq	($A,32);
259e1051a39Sopenharmony_ci	&pop	("esi");
260e1051a39Sopenharmony_ci	&pxor	($R,"mm6");
261e1051a39Sopenharmony_ci	&pop	("ebx");
262e1051a39Sopenharmony_ci	&pxor	($A,"mm7");
263e1051a39Sopenharmony_ci	&movq	(&QWP(0,$a),$R);
264e1051a39Sopenharmony_ci	&pop	("ebp");
265e1051a39Sopenharmony_ci	&movq	(&QWP(8,$a),$A);
266e1051a39Sopenharmony_ci	&emms	();
267e1051a39Sopenharmony_ci	&ret	();
268e1051a39Sopenharmony_ci&set_label("ialu",16);
269e1051a39Sopenharmony_ci}
270e1051a39Sopenharmony_ci	&push	("ebp");
271e1051a39Sopenharmony_ci	&push	("ebx");
272e1051a39Sopenharmony_ci	&push	("esi");
273e1051a39Sopenharmony_ci	&push	("edi");
274e1051a39Sopenharmony_ci	&stack_push(4+1);
275e1051a39Sopenharmony_ci
276e1051a39Sopenharmony_ci	&mov	($a,&wparam(1));
277e1051a39Sopenharmony_ci	&mov	($b,&wparam(3));
278e1051a39Sopenharmony_ci	&call	("_mul_1x1_ialu");	# a1·b1
279e1051a39Sopenharmony_ci	&mov	(&DWP(8,"esp"),$lo);
280e1051a39Sopenharmony_ci	&mov	(&DWP(12,"esp"),$hi);
281e1051a39Sopenharmony_ci
282e1051a39Sopenharmony_ci	&mov	($a,&wparam(2));
283e1051a39Sopenharmony_ci	&mov	($b,&wparam(4));
284e1051a39Sopenharmony_ci	&call	("_mul_1x1_ialu");	# a0·b0
285e1051a39Sopenharmony_ci	&mov	(&DWP(0,"esp"),$lo);
286e1051a39Sopenharmony_ci	&mov	(&DWP(4,"esp"),$hi);
287e1051a39Sopenharmony_ci
288e1051a39Sopenharmony_ci	&mov	($a,&wparam(1));
289e1051a39Sopenharmony_ci	&mov	($b,&wparam(3));
290e1051a39Sopenharmony_ci	&xor	($a,&wparam(2));
291e1051a39Sopenharmony_ci	&xor	($b,&wparam(4));
292e1051a39Sopenharmony_ci	&call	("_mul_1x1_ialu");	# (a0+a1)·(b0+b1)
293e1051a39Sopenharmony_ci
294e1051a39Sopenharmony_ci	&mov	("ebp",&wparam(0));
295e1051a39Sopenharmony_ci		 @r=("ebx","ecx","edi","esi");
296e1051a39Sopenharmony_ci	&mov	(@r[0],&DWP(0,"esp"));
297e1051a39Sopenharmony_ci	&mov	(@r[1],&DWP(4,"esp"));
298e1051a39Sopenharmony_ci	&mov	(@r[2],&DWP(8,"esp"));
299e1051a39Sopenharmony_ci	&mov	(@r[3],&DWP(12,"esp"));
300e1051a39Sopenharmony_ci
301e1051a39Sopenharmony_ci	&xor	($lo,$hi);
302e1051a39Sopenharmony_ci	&xor	($hi,@r[1]);
303e1051a39Sopenharmony_ci	&xor	($lo,@r[0]);
304e1051a39Sopenharmony_ci	&mov	(&DWP(0,"ebp"),@r[0]);
305e1051a39Sopenharmony_ci	&xor	($hi,@r[2]);
306e1051a39Sopenharmony_ci	&mov	(&DWP(12,"ebp"),@r[3]);
307e1051a39Sopenharmony_ci	&xor	($lo,@r[3]);
308e1051a39Sopenharmony_ci	&stack_pop(4+1);
309e1051a39Sopenharmony_ci	&xor	($hi,@r[3]);
310e1051a39Sopenharmony_ci	&pop	("edi");
311e1051a39Sopenharmony_ci	&xor	($lo,$hi);
312e1051a39Sopenharmony_ci	&pop	("esi");
313e1051a39Sopenharmony_ci	&mov	(&DWP(8,"ebp"),$hi);
314e1051a39Sopenharmony_ci	&pop	("ebx");
315e1051a39Sopenharmony_ci	&mov	(&DWP(4,"ebp"),$lo);
316e1051a39Sopenharmony_ci	&pop	("ebp");
317e1051a39Sopenharmony_ci	&ret	();
318e1051a39Sopenharmony_ci&function_end_B("bn_GF2m_mul_2x2");
319e1051a39Sopenharmony_ci
320e1051a39Sopenharmony_ci&asciz	("GF(2^m) Multiplication for x86, CRYPTOGAMS by <appro\@openssl.org>");
321e1051a39Sopenharmony_ci
322e1051a39Sopenharmony_ci&asm_finish();
323e1051a39Sopenharmony_ci
324e1051a39Sopenharmony_ciclose STDOUT or die "error closing STDOUT: $!";
325