ghash-x86.pl: omit unreferenced rem_8bit from no-sse2 build.
[openssl.git] / crypto / modes / asm / ghash-x86.pl
index fca19e41f0849da914eb65f356e34ab3811ff320..2a1819cb515969faefae10a222a2688c24c357a4 100644 (file)
 # The module implements "4-bit" GCM GHASH function and underlying
 # single multiplication operation in GF(2^128). "4-bit" means that it
 # uses 256 bytes per-key table [+64/128 bytes fixed table]. It has two
-# code paths: vanilla x86 and vanilla MMX. Former will be executed on
-# 486 and Pentium, latter on all others. MMX GHASH features so called
+# code paths: vanilla x86 and vanilla SSE. Former will be executed on
+# 486 and Pentium, latter on all others. SSE GHASH features so called
 # "528B" variant of "4-bit" method utilizing additional 256+16 bytes
 # of per-key storage [+512 bytes shared table]. Performance results
 # are for streamed GHASH subroutine and are expressed in cycles per
 # processed byte, less is better:
 #
-#              gcc 2.95.3(*)   MMX assembler   x86 assembler
+#              gcc 2.95.3(*)   SSE assembler   x86 assembler
 #
 # Pentium      105/111(**)     -               50
 # PIII         68 /75          12.2            24
@@ -30,7 +30,7 @@
 # (*)  gcc 3.4.x was observed to generate few percent slower code,
 #      which is one of reasons why 2.95.3 results were chosen,
 #      another reason is lack of 3.4.x results for older CPUs;
-#      comparison with MMX results is not completely fair, because C
+#      comparison with SSE results is not completely fair, because C
 #      results are for vanilla "256B" implementation, while
 #      assembler results are for "528B";-)
 # (**) second number is result for code compiled with -fPIC flag,
@@ -40,8 +40,8 @@
 #
 # To summarize, it's >2-5 times faster than gcc-generated code. To
 # anchor it to something else SHA1 assembler processes one byte in
-# 11-13 cycles on contemporary x86 cores. As for choice of MMX in
-# particular, see comment at the end of the file...
+# ~7 cycles on contemporary x86 cores. As for choice of MMX/SSE
+# in particular, see comment at the end of the file...
 
 # May 2010
 #
 # providing access to a Westmere-based system on behalf of Intel
 # Open Source Technology Centre.
 
+# January 2010
+#
+# Tweaked to optimize transitions between integer and FP operations
+# on same XMM register, PCLMULQDQ subroutine was measured to process
+# one byte in 2.07 cycles on Sandy Bridge, and in 2.12 - on Westmere.
+# The minor regression on Westmere is outweighed by ~15% improvement
+# on Sandy Bridge. Strangely enough attempt to modify 64-bit code in
+# similar manner resulted in almost 20% degradation on Sandy Bridge,
+# where original 64-bit code processes one byte in 1.95 cycles.
+
 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
 push(@INC,"${dir}","${dir}../../perlasm");
 require "x86asm.pl";
@@ -321,7 +331,7 @@ if (!$x86only) {{{
 
 &static_label("rem_4bit");
 
-if (0) {{      # "May" MMX version is kept for reference...
+if (!$sse2) {{ # pure-MMX "May" version...
 
 $S=12;         # shift factor for rem_4bit
 
@@ -811,12 +821,6 @@ $len="ebx";
 
 &static_label("bswap");
 
-sub pclmulqdq
-{ my($dst,$src,$imm)=@_;
-    if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
-    {  &data_byte(0x66,0x0f,0x3a,0x44,0xc0|($1<<3)|$2,$imm);   }
-}
-
 sub clmul64x64_T2 {    # minimal "register" pressure
 my ($Xhi,$Xi,$Hkey)=@_;
 
@@ -829,8 +833,8 @@ my ($Xhi,$Xi,$Hkey)=@_;
        &pclmulqdq      ($Xi,$Hkey,0x00);       #######
        &pclmulqdq      ($Xhi,$Hkey,0x11);      #######
        &pclmulqdq      ($T1,$T2,0x00);         #######
-       &pxor           ($T1,$Xi);              #
-       &pxor           ($T1,$Xhi);             #
+       &xorps          ($T1,$Xi);              #
+       &xorps          ($T1,$Xhi);             #
 
        &movdqa         ($T2,$T1);              #
        &psrldq         ($T1,8);
@@ -950,7 +954,7 @@ my ($Xhi,$Xi) = @_;
 
        &movdqu         ($Xi,&QWP(0,$Xip));
        &movdqa         ($T3,&QWP(0,$const));
-       &movdqu         ($Hkey,&QWP(0,$Htbl));
+       &movups         ($Hkey,&QWP(0,$Htbl));
        &pshufb         ($Xi,$T3);
 
        &clmul64x64_T2  ($Xhi,$Xi,$Hkey);
@@ -993,7 +997,7 @@ my ($Xhi,$Xi) = @_;
        &pxor           ($Xi,$T1);              # Ii+Xi
 
        &clmul64x64_T2  ($Xhn,$Xn,$Hkey);       # H*Ii+1
-       &movdqu         ($Hkey,&QWP(16,$Htbl)); # load H^2
+       &movups         ($Hkey,&QWP(16,$Htbl)); # load H^2
 
        &lea            ($inp,&DWP(32,$inp));   # i+=2
        &sub            ($len,0x20);
@@ -1002,7 +1006,7 @@ my ($Xhi,$Xi) = @_;
 &set_label("mod_loop");
        &clmul64x64_T2  ($Xhi,$Xi,$Hkey);       # H^2*(Ii+Xi)
        &movdqu         ($T1,&QWP(0,$inp));     # Ii
-       &movdqu         ($Hkey,&QWP(0,$Htbl));  # load H
+       &movups         ($Hkey,&QWP(0,$Htbl));  # load H
 
        &pxor           ($Xi,$Xn);              # (H*Ii+1) + H^2*(Ii+Xi)
        &pxor           ($Xhi,$Xhn);
@@ -1043,9 +1047,9 @@ my ($Xhi,$Xi) = @_;
          &pxor         ($Xi,$T2);              #
 
        &pclmulqdq      ($T1,$T3,0x00);         #######
-       &movdqu         ($Hkey,&QWP(16,$Htbl)); # load H^2
-       &pxor           ($T1,$Xn);              #
-       &pxor           ($T1,$Xhn);             #
+       &movups         ($Hkey,&QWP(16,$Htbl)); # load H^2
+       &xorps          ($T1,$Xn);              #
+       &xorps          ($T1,$Xhn);             #
 
        &movdqa         ($T3,$T1);              #
        &psrldq         ($T1,8);
@@ -1069,7 +1073,7 @@ my ($Xhi,$Xi) = @_;
        &test           ($len,$len);
        &jnz            (&label("done"));
 
-       &movdqu         ($Hkey,&QWP(0,$Htbl));  # load H
+       &movups         ($Hkey,&QWP(0,$Htbl));  # load H
 &set_label("odd_tail");
        &movdqu         ($T1,&QWP(0,$inp));     # Ii
        &pshufb         ($T1,$T3);
@@ -1269,13 +1273,6 @@ my ($Xhi,$Xi)=@_;
 &set_label("bswap",64);
        &data_byte(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0);
        &data_byte(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2); # 0x1c2_polynomial
-}}     # $sse2
-
-&set_label("rem_4bit",64);
-       &data_word(0,0x0000<<$S,0,0x1C20<<$S,0,0x3840<<$S,0,0x2460<<$S);
-       &data_word(0,0x7080<<$S,0,0x6CA0<<$S,0,0x48C0<<$S,0,0x54E0<<$S);
-       &data_word(0,0xE100<<$S,0,0xFD20<<$S,0,0xD940<<$S,0,0xC560<<$S);
-       &data_word(0,0x9180<<$S,0,0x8DA0<<$S,0,0xA9C0<<$S,0,0xB5E0<<$S);
 &set_label("rem_8bit",64);
        &data_short(0x0000,0x01C2,0x0384,0x0246,0x0708,0x06CA,0x048C,0x054E);
        &data_short(0x0E10,0x0FD2,0x0D94,0x0C56,0x0918,0x08DA,0x0A9C,0x0B5E);
@@ -1309,6 +1306,13 @@ my ($Xhi,$Xi)=@_;
        &data_short(0xA7D0,0xA612,0xA454,0xA596,0xA0D8,0xA11A,0xA35C,0xA29E);
        &data_short(0xB5E0,0xB422,0xB664,0xB7A6,0xB2E8,0xB32A,0xB16C,0xB0AE);
        &data_short(0xBBF0,0xBA32,0xB874,0xB9B6,0xBCF8,0xBD3A,0xBF7C,0xBEBE);
+}}     # $sse2
+
+&set_label("rem_4bit",64);
+       &data_word(0,0x0000<<$S,0,0x1C20<<$S,0,0x3840<<$S,0,0x2460<<$S);
+       &data_word(0,0x7080<<$S,0,0x6CA0<<$S,0,0x48C0<<$S,0,0x54E0<<$S);
+       &data_word(0,0xE100<<$S,0,0xFD20<<$S,0,0xD940<<$S,0,0xC560<<$S);
+       &data_word(0,0x9180<<$S,0,0x8DA0<<$S,0,0xA9C0<<$S,0,0xB5E0<<$S);
 }}}    # !$x86only
 
 &asciz("GHASH for x86, CRYPTOGAMS by <appro\@openssl.org>");