⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mo-586.pl

📁 OpenSSL 0.9.8k 最新版OpenSSL
💻 PL
📖 第 1 页 / 共 2 页
字号:
#!/usr/bin/env perl# This is crypto/bn/asm/x86-mont.pl (with asciz from crypto/perlasm/x86asm.pl)# from OpenSSL 0.9.9-dev sub ::asciz{ my @str=unpack("C*",shift);    push @str,0;    while ($#str>15) {	&data_byte(@str[0..15]);	foreach (0..15) { shift @str; }    }    &data_byte(@str) if (@str);}# ====================================================================# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL# project. The module is, however, dual licensed under OpenSSL and# CRYPTOGAMS licenses depending on where you obtain it. For further# details see http://www.openssl.org/~appro/cryptogams/.# ====================================================================# October 2005## This is a "teaser" code, as it can be improved in several ways...# First of all non-SSE2 path should be implemented (yes, for now it# performs Montgomery multiplication/convolution only on SSE2-capable# CPUs such as P4, others fall down to original code). Then inner loop# can be unrolled and modulo-scheduled to improve ILP and possibly# moved to 128-bit XMM register bank (though it would require input# rearrangement and/or increase bus bandwidth utilization). Dedicated# squaring procedure should give further performance improvement...# Yet, for being draft, the code improves rsa512 *sign* benchmark by# 110%(!), rsa1024 one - by 70% and rsa4096 - by 20%:-)# December 2006## Modulo-scheduling SSE2 loops results in further 15-20% improvement.# Integer-only code [being equipped with dedicated squaring procedure]# gives ~40% on rsa512 sign benchmark...push(@INC,"perlasm","../../perlasm");require "x86asm.pl";&asm_init($ARGV[0],$0);$sse2=0;for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }&external_label("OPENSSL_ia32cap_P") if ($sse2);&function_begin("bn_mul_mont");$i="edx";$j="ecx";$ap="esi";	$tp="esi";		# overlapping variables!!!$rp="edi";	$bp="edi";		# overlapping variables!!!$np="ebp";$num="ebx";$_num=&DWP(4*0,"esp");			# stack top layout$_rp=&DWP(4*1,"esp");$_ap=&DWP(4*2,"esp");$_bp=&DWP(4*3,"esp");$_np=&DWP(4*4,"esp");$_n0=&DWP(4*5,"esp");	$_n0q=&QWP(4*5,"esp");$_sp=&DWP(4*6,"esp");$_bpend=&DWP(4*7,"esp");$frame=32;				# size of above frame rounded up to 16n	&xor	("eax","eax");	&mov	("edi",&wparam(5));	# int num	&cmp	("edi",4);	&jl	(&label("just_leave"));	&lea	("esi",&wparam(0));	# put aside pointer to argument block	&lea	("edx",&wparam(1));	# load ap	&mov	("ebp","esp");		# saved stack pointer!	&add	("edi",2);		# extra two words on top of tp	&neg	("edi");	&lea	("esp",&DWP(-$frame,"esp","edi",4));	# alloca($frame+4*(num+2))	&neg	("edi");	# minimize cache contention by arraning 2K window between stack	# pointer and ap argument [np is also position sensitive vector,	# but it's assumed to be near ap, as it's allocated at ~same	# time].	&mov	("eax","esp");	&sub	("eax","edx");	&and	("eax",2047);	&sub	("esp","eax");		# this aligns sp and ap modulo 2048	&xor	("edx","esp");	&and	("edx",2048);	&xor	("edx",2048);	&sub	("esp","edx");		# this splits them apart modulo 4096	&and	("esp",-64);		# align to cache line	################################# load argument block...	&mov	("eax",&DWP(0*4,"esi"));# BN_ULONG *rp	&mov	("ebx",&DWP(1*4,"esi"));# const BN_ULONG *ap	&mov	("ecx",&DWP(2*4,"esi"));# const BN_ULONG *bp	&mov	("edx",&DWP(3*4,"esi"));# const BN_ULONG *np	&mov	("esi",&DWP(4*4,"esi"));# const BN_ULONG *n0	#&mov	("edi",&DWP(5*4,"esi"));# int num	&mov	("esi",&DWP(0,"esi"));	# pull n0[0]	&mov	($_rp,"eax");		# ... save a copy of argument block	&mov	($_ap,"ebx");	&mov	($_bp,"ecx");	&mov	($_np,"edx");	&mov	($_n0,"esi");	&lea	($num,&DWP(-3,"edi"));	# num=num-1 to assist modulo-scheduling	#&mov	($_num,$num);		# redundant as $num is not reused	&mov	($_sp,"ebp");		# saved stack pointer!if($sse2) {$acc0="mm0";	# mmx register bank layout$acc1="mm1";$car0="mm2";$car1="mm3";$mul0="mm4";$mul1="mm5";$temp="mm6";$mask="mm7";	&picmeup("eax","OPENSSL_ia32cap_P");	&bt	(&DWP(0,"eax"),26);	&jnc	(&label("non_sse2"));	&mov	("eax",-1);	&movd	($mask,"eax");		# mask 32 lower bits	&mov	($ap,$_ap);		# load input pointers	&mov	($bp,$_bp);	&mov	($np,$_np);	&xor	($i,$i);		# i=0	&xor	($j,$j);		# j=0	&movd	($mul0,&DWP(0,$bp));		# bp[0]	&movd	($mul1,&DWP(0,$ap));		# ap[0]	&movd	($car1,&DWP(0,$np));		# np[0]	&pmuludq($mul1,$mul0);			# ap[0]*bp[0]	&movq	($car0,$mul1);	&movq	($acc0,$mul1);			# I wish movd worked for	&pand	($acc0,$mask);			# inter-register transfers	&pmuludq($mul1,$_n0q);			# *=n0	&pmuludq($car1,$mul1);			# "t[0]"*np[0]*n0	&paddq	($car1,$acc0);	&movd	($acc1,&DWP(4,$np));		# np[1]	&movd	($acc0,&DWP(4,$ap));		# ap[1]	&psrlq	($car0,32);	&psrlq	($car1,32);	&inc	($j);				# j++&set_label("1st",16);	&pmuludq($acc0,$mul0);			# ap[j]*bp[0]	&pmuludq($acc1,$mul1);			# np[j]*m1	&paddq	($car0,$acc0);			# +=c0	&paddq	($car1,$acc1);			# +=c1	&movq	($acc0,$car0);	&pand	($acc0,$mask);	&movd	($acc1,&DWP(4,$np,$j,4));	# np[j+1]	&paddq	($car1,$acc0);			# +=ap[j]*bp[0];	&movd	($acc0,&DWP(4,$ap,$j,4));	# ap[j+1]	&psrlq	($car0,32);	&movd	(&DWP($frame-4,"esp",$j,4),$car1);	# tp[j-1]=	&psrlq	($car1,32);	&lea	($j,&DWP(1,$j));	&cmp	($j,$num);	&jl	(&label("1st"));	&pmuludq($acc0,$mul0);			# ap[num-1]*bp[0]	&pmuludq($acc1,$mul1);			# np[num-1]*m1	&paddq	($car0,$acc0);			# +=c0	&paddq	($car1,$acc1);			# +=c1	&movq	($acc0,$car0);	&pand	($acc0,$mask);	&paddq	($car1,$acc0);			# +=ap[num-1]*bp[0];	&movd	(&DWP($frame-4,"esp",$j,4),$car1);	# tp[num-2]=	&psrlq	($car0,32);	&psrlq	($car1,32);	&paddq	($car1,$car0);	&movq	(&QWP($frame,"esp",$num,4),$car1);	# tp[num].tp[num-1]	&inc	($i);				# i++&set_label("outer");	&xor	($j,$j);			# j=0	&movd	($mul0,&DWP(0,$bp,$i,4));	# bp[i]	&movd	($mul1,&DWP(0,$ap));		# ap[0]	&movd	($temp,&DWP($frame,"esp"));	# tp[0]	&movd	($car1,&DWP(0,$np));		# np[0]	&pmuludq($mul1,$mul0);			# ap[0]*bp[i]	&paddq	($mul1,$temp);			# +=tp[0]	&movq	($acc0,$mul1);	&movq	($car0,$mul1);	&pand	($acc0,$mask);	&pmuludq($mul1,$_n0q);			# *=n0	&pmuludq($car1,$mul1);	&paddq	($car1,$acc0);	&movd	($temp,&DWP($frame+4,"esp"));	# tp[1]	&movd	($acc1,&DWP(4,$np));		# np[1]	&movd	($acc0,&DWP(4,$ap));		# ap[1]	&psrlq	($car0,32);	&psrlq	($car1,32);	&paddq	($car0,$temp);			# +=tp[1]	&inc	($j);				# j++	&dec	($num);&set_label("inner");	&pmuludq($acc0,$mul0);			# ap[j]*bp[i]	&pmuludq($acc1,$mul1);			# np[j]*m1	&paddq	($car0,$acc0);			# +=c0	&paddq	($car1,$acc1);			# +=c1	&movq	($acc0,$car0);	&movd	($temp,&DWP($frame+4,"esp",$j,4));# tp[j+1]	&pand	($acc0,$mask);	&movd	($acc1,&DWP(4,$np,$j,4));	# np[j+1]	&paddq	($car1,$acc0);			# +=ap[j]*bp[i]+tp[j]	&movd	($acc0,&DWP(4,$ap,$j,4));	# ap[j+1]	&psrlq	($car0,32);	&movd	(&DWP($frame-4,"esp",$j,4),$car1);# tp[j-1]=	&psrlq	($car1,32);	&paddq	($car0,$temp);			# +=tp[j+1]	&dec	($num);	&lea	($j,&DWP(1,$j));		# j++	&jnz	(&label("inner"));	&mov	($num,$j);	&pmuludq($acc0,$mul0);			# ap[num-1]*bp[i]	&pmuludq($acc1,$mul1);			# np[num-1]*m1	&paddq	($car0,$acc0);			# +=c0	&paddq	($car1,$acc1);			# +=c1	&movq	($acc0,$car0);	&pand	($acc0,$mask);	&paddq	($car1,$acc0);			# +=ap[num-1]*bp[i]+tp[num-1]	&movd	(&DWP($frame-4,"esp",$j,4),$car1);	# tp[num-2]=	&psrlq	($car0,32);	&psrlq	($car1,32);	&movd	($temp,&DWP($frame+4,"esp",$num,4));	# += tp[num]	&paddq	($car1,$car0);	&paddq	($car1,$temp);	&movq	(&QWP($frame,"esp",$num,4),$car1);	# tp[num].tp[num-1]	&lea	($i,&DWP(1,$i));		# i++	&cmp	($i,$num);	&jle	(&label("outer"));	&emms	();				# done with mmx bank	&jmp	(&label("common_tail"));&set_label("non_sse2",16);}if (0) {	&mov	("esp",$_sp);	&xor	("eax","eax");	# signal "not fast enough [yet]"	&jmp	(&label("just_leave"));	# While the below code provides competitive performance for	# all key lengthes on modern Intel cores, it's still more	# than 10% slower for 4096-bit key elsewhere:-( "Competitive"	# means compared to the original integer-only assembler.	# 512-bit RSA sign is better by ~40%, but that's about all	# one can say about all CPUs...} else {$inp="esi";	# integer path uses these registers differently$word="edi";$carry="ebp";	&mov	($inp,$_ap);	&lea	($carry,&DWP(1,$num));	&mov	($word,$_bp);	&xor	($j,$j);				# j=0	&mov	("edx",$inp);	&and	($carry,1);				# see if num is even	&sub	("edx",$word);				# see if ap==bp	&lea	("eax",&DWP(4,$word,$num,4));		# &bp[num]	&or	($carry,"edx");	&mov	($word,&DWP(0,$word));			# bp[0]	&jz	(&label("bn_sqr_mont"));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -