Fix OPENSSL_BN_ASM_MONT5 for corner cases; add a test.
[openssl.git] / crypto / x86cpuid.pl
index f424c2debeed80da5038f4ec0740e918322a9a8a..6595ff35fc1bbcbf6a4619a56088e48e7b2bd39b 100644 (file)
@@ -92,13 +92,15 @@ for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
 &set_label("nocacheinfo");
        &mov    ("eax",1);
        &cpuid  ();
+       &and    ("edx",0xbfefffff);     # force reserved bits #20, #30 to 0
        &cmp    ("ebp",0);
-       &jne    (&label("notP4"));
+       &jne    (&label("notintel"));
+       &or     ("edx",1<<30);          # set reserved bit#30 on Intel CPUs
        &and    (&HB("eax"),15);        # familiy ID
        &cmp    (&HB("eax"),15);        # P4?
-       &jne    (&label("notP4"));
-       &or     ("edx",1<<20);          # use reserved bit to engage RC4_CHAR
-&set_label("notP4");
+       &jne    (&label("notintel"));
+       &or     ("edx",1<<20);          # set reserved bit#20 to engage RC4_CHAR
+&set_label("notintel");
        &bt     ("edx",28);             # test hyper-threading bit
        &jnc    (&label("generic"));
        &and    ("edx",0xefffffff);
@@ -113,7 +115,7 @@ for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
 
 &set_label("generic");
        &and    ("ebp",1<<11);          # isolate AMD XOP flag
-       &and    ("ecx",~(1<<11));
+       &and    ("ecx",0xfffff7ff);     # force 11th bit to 0
        &mov    ("esi","edx");
        &or     ("ebp","ecx");          # merge AMD XOP flag
 
@@ -129,10 +131,10 @@ for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
        &cmp    ("eax",2);
        &je     (&label("clear_avx"));
 &set_label("clear_xmm");
-       &and    ("ebp",~(1<<25|1<<1));  # clear AESNI and PCLMULQDQ bits
-       &and    ("esi",~(1<<24));       # clear FXSR
+       &and    ("ebp",0xfdfffffd);     # clear AESNI and PCLMULQDQ bits
+       &and    ("esi",0xfeffffff);     # clear FXSR
 &set_label("clear_avx");
-       &and    ("ebp",~(1<<28|1<<12|1<<11));# clear AVX, FMA and AMD XOP bits
+       &and    ("ebp",0xefffe7ff);     # clear AVX, FMA and AMD XOP bits
 &set_label("done");
        &mov    ("eax","esi");
        &mov    ("edx","ebp");
@@ -440,6 +442,18 @@ my $max = "ebp";
 &function_end("OPENSSL_instrument_bus2");
 }
 
+&function_begin_B("OPENSSL_ia32_rdrand");
+       &mov    ("ecx",8);
+&set_label("loop");
+       &rdrand ("eax");
+       &jc     (&label("break"));
+       &loop   (&label("loop"));
+&set_label("break");
+       &cmp    ("eax",0);
+       &cmove  ("eax","ecx");
+       &ret    ();
+&function_end_B("OPENSSL_ia32_rdrand");
+
 &initseg("OPENSSL_cpuid_setup");
 
 &asm_finish();