push(@INC,"perlasm");
require "x86asm.pl";
&asm_init($ARGV[0],"x86cpuid");
for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
&function_begin("OPENSSL_ia32_cpuid");
&xor ("edx","edx");
&pushf ();
&pop ("eax");
&mov ("ecx","eax");
&xor ("eax",1<<21);
&push ("eax");
&popf ();
&pushf ();
&pop ("eax");
&xor ("ecx","eax");
&bt ("ecx",21);
&jnc (&label("done"));
&xor ("eax","eax");
&cpuid ();
&xor ("eax","eax");
&cmp ("ebx",0x756e6547); &data_byte(0x0f,0x95,0xc0); &mov ("ebp","eax");
&cmp ("edx",0x49656e69); &data_byte(0x0f,0x95,0xc0); &or ("ebp","eax");
&cmp ("ecx",0x6c65746e); &data_byte(0x0f,0x95,0xc0); &or ("ebp","eax");
&mov ("eax",1);
&cpuid ();
&cmp ("ebp",0);
&jne (&label("notP4"));
&and ("eax",15<<8); &cmp ("eax",15<<8); &jne (&label("notP4"));
&or ("edx",1<<20); &set_label("notP4");
&bt ("edx",28); &jnc (&label("done"));
&shr ("ebx",16);
&and ("ebx",0xff);
&cmp ("ebx",1); &ja (&label("done"));
&and ("edx",0xefffffff); &set_label("done");
&mov ("eax","edx");
&mov ("edx","ecx");
&function_end("OPENSSL_ia32_cpuid");
&external_label("OPENSSL_ia32cap_P");
&function_begin_B("OPENSSL_rdtsc","EXTRN\t_OPENSSL_ia32cap_P:DWORD");
&xor ("eax","eax");
&xor ("edx","edx");
&picmeup("ecx","OPENSSL_ia32cap_P");
&bt (&DWP(0,"ecx"),4);
&jnc (&label("notsc"));
&rdtsc ();
&set_label("notsc");
&ret ();
&function_end_B("OPENSSL_rdtsc");
&function_begin_B("OPENSSL_instrument_halt","EXTRN\t_OPENSSL_ia32cap_P:DWORD");
&picmeup("ecx","OPENSSL_ia32cap_P");
&bt (&DWP(0,"ecx"),4);
&jnc (&label("nohalt"));
&data_word(0x9058900e); &and ("eax",3);
&jnz (&label("nohalt"));
&pushf ();
&pop ("eax")
&bt ("eax",9);
&jnc (&label("nohalt"));
&rdtsc ();
&push ("edx");
&push ("eax");
&halt ();
&rdtsc ();
&sub ("eax",&DWP(0,"esp"));
&sbb ("edx",&DWP(4,"esp"));
&add ("esp",8);
&ret ();
&set_label("nohalt");
&xor ("eax","eax");
&xor ("edx","edx");
&ret ();
&function_end_B("OPENSSL_instrument_halt");
&function_begin_B("OPENSSL_far_spin");
&pushf ();
&pop ("eax")
&bt ("eax",9);
&jnc (&label("nospin"));
&mov ("eax",&DWP(4,"esp"));
&mov ("ecx",&DWP(8,"esp"));
&data_word (0x90d88e1e); &xor ("eax","eax");
&mov ("edx",&DWP(0,"ecx"));
&jmp (&label("spin"));
&align (16);
&set_label("spin");
&inc ("eax");
&cmp ("edx",&DWP(0,"ecx"));
&je (&label("spin"));
&data_word (0x1f909090); &ret ();
&set_label("nospin");
&xor ("eax","eax");
&xor ("edx","edx");
&ret ();
&function_end_B("OPENSSL_far_spin");
&function_begin_B("OPENSSL_wipe_cpu","EXTRN\t_OPENSSL_ia32cap_P:DWORD");
&xor ("eax","eax");
&xor ("edx","edx");
&picmeup("ecx","OPENSSL_ia32cap_P");
&mov ("ecx",&DWP(0,"ecx"));
&bt (&DWP(0,"ecx"),1);
&jnc (&label("no_x87"));
if ($sse2) {
&bt (&DWP(0,"ecx"),26);
&jnc (&label("no_sse2"));
&pxor ("xmm0","xmm0");
&pxor ("xmm1","xmm1");
&pxor ("xmm2","xmm2");
&pxor ("xmm3","xmm3");
&pxor ("xmm4","xmm4");
&pxor ("xmm5","xmm5");
&pxor ("xmm6","xmm6");
&pxor ("xmm7","xmm7");
&set_label("no_sse2");
}
&data_word(0xeed9eed9,0xeed9eed9,0xeed9eed9,0xeed9eed9,0x90e3db9b);
&set_label("no_x87");
&lea ("eax",&DWP(4,"esp"));
&ret ();
&function_end_B("OPENSSL_wipe_cpu");
&function_begin_B("OPENSSL_atomic_add");
&mov ("edx",&DWP(4,"esp")); &mov ("ecx",&DWP(8,"esp")); &push ("ebx");
&nop ();
&mov ("eax",&DWP(0,"edx"));
&set_label("spin");
&lea ("ebx",&DWP(0,"eax","ecx"));
&nop ();
&data_word(0x1ab10ff0); &jne (&label("spin"));
&mov ("eax","ebx"); &pop ("ebx");
&ret ();
&function_end_B("OPENSSL_atomic_add");
&function_begin_B("OPENSSL_indirect_call");
{
my $i,$max=7; &push ("ebp");
&mov ("ebp","esp");
&sub ("esp",$max*4);
&mov ("ecx",&DWP(12,"ebp"));
&mov (&DWP(0,"esp"),"ecx");
&mov ("edx",&DWP(16,"ebp"));
&mov (&DWP(4,"esp"),"edx");
for($i=2;$i<$max;$i++)
{
&mov ("eax",&DWP(12+$i*4,"ebp"));
&mov (&DWP(0+$i*4,"esp"),"eax");
}
&call_ptr (&DWP(8,"ebp")); &mov ("esp","ebp"); &pop ("ebp");
&ret ();
}
&function_end_B("OPENSSL_indirect_call");
&initseg("OPENSSL_cpuid_setup");
&asm_finish();