x86 perlasm overhaul.
[openssl.git] / crypto / perlasm / x86nasm.pl
index 604f58a..1154f04 100644 (file)
@@ -4,11 +4,10 @@ package x86nasm;
 
 *out=\@::out;
 
-$lbdecor="\@L";                        # local label decoration
+$::lbdecor="\@L";              # local label decoration
 $nmdecor=$::netware?"":"_";    # external name decoration
 $drdecor=$::mwerks?".":"";     # directive decoration
 
-$label="000";
 $initseg="";
 
 sub ::generic
@@ -18,7 +17,7 @@ sub ::generic
     if (!$::mwerks)
     {   if    ($opcode =~ m/^j/o && $#_==0) # optimize jumps
        {   $_[0] = "NEAR $_[0]";       }
-       elsif ($opcode eq "lea" && $#_==1)# wipe storage qualifier from lea
+       elsif ($opcode eq "lea" && $#_==1)  # wipe storage qualifier from lea
        {   $_[1] =~ s/^[^\[]*\[/\[/o;  }
     }
     &::emit($opcode,@_);
@@ -27,26 +26,10 @@ sub ::generic
 #
 # opcodes not covered by ::generic above, mostly inconsistent namings...
 #
-sub ::movz     { &::movzx(@_);         }
-sub ::pushf    { &::pushfd;            }
-sub ::popf     { &::popfd;             }
-
-sub ::call     { &::emit("call",(&islabel($_[0]) or "$nmdecor$_[0]")); }
+sub ::call     { &::emit("call",(&::islabel($_[0]) or "$nmdecor$_[0]")); }
 sub ::call_ptr { &::emit("call",@_);   }
 sub ::jmp_ptr  { &::emit("jmp",@_);    }
 
-# chosen SSE instructions
-sub ::movq
-{ my($p1,$p2,$optimize)=@_;
-
-    if ($optimize && $p1=~/^mm[0-7]$/ && $p2=~/^mm[0-7]$/)
-    # movq between mmx registers can sink Intel CPUs
-    {  &::pshufw($p1,$p2,0xe4);                }
-    else
-    {  &::emit("movq",@_);                     }
-}
-sub ::pshufw { &::emit("pshufw",@_); }
-
 sub get_mem
 { my($size,$addr,$reg1,$reg2,$idx)=@_;
   my($post,$ret);
@@ -60,7 +43,7 @@ sub get_mem
 
     $addr =~ s/^\s+//;
     # prepend global references with optional underscore
-    $addr =~ s/^([^\+\-0-9][^\+\-]*)/islabel($1) or "$nmdecor$1"/ige;
+    $addr =~ s/^([^\+\-0-9][^\+\-]*)/::islabel($1) or "$nmdecor$1"/ige;
     # put address arithmetic expression in parenthesis
     $addr="($addr)" if ($addr =~ /^.+[\-\+].+$/);
 
@@ -89,7 +72,7 @@ sub ::BC      { (($::mwerks)?"":"BYTE ")."@_";  }
 sub ::DWC      { (($::mwerks)?"":"DWORD ")."@_"; }
 
 sub ::file
-{   if ($::mwerks)     { push(@out,".section\t.text\n"); }
+{   if ($::mwerks)     { push(@out,".section\t.text,64\n"); }
     else
     { my $tmp=<<___;
 %ifdef __omf__
@@ -105,9 +88,11 @@ ___
 sub ::function_begin_B
 { my $func=shift;
   my $global=($func !~ /^_/);
-  my $begin="${lbdecor}_${func}_begin";
+  my $begin="${::lbdecor}_${func}_begin";
 
-    $label{$func}=$global?"$begin":"$nmdecor$func";
+    $begin =~ s/^\@/./ if ($::mwerks); # the torture never stops
+
+    &::LABEL($func,$global?"$begin":"$nmdecor$func");
     $func=$nmdecor.$func;
 
     push(@out,"${drdecor}global        $func\n")       if ($global);
@@ -116,122 +101,32 @@ sub ::function_begin_B
     push(@out,"$begin:\n")                     if ($global);
     $::stack=4;
 }
+
 sub ::function_end_B
-{ my $i;
-    foreach $i (keys %label)
-    {  delete $label{$i} if ($label{$i} =~ /^${lbdecor}[0-9]{3}/);     }
-    $::stack=0;
+{   $::stack=0;
+    &::wipe_labels();
 }
 
 sub ::file_end
-{   # try to detect if SSE2 or MMX extensions were used on Win32...
-    if ($::win32 && grep {/\b[x]?mm[0-7]\b|OPENSSL_ia32cap_P\b/i} @out)
-    {  # $1<<10 sets a reserved bit to signal that variable
-       # was initialized already...
-       my $code=<<___;
-align  16
-${lbdecor}OPENSSL_ia32cap_init:
-       lea     edx,[${nmdecor}OPENSSL_ia32cap_P]
-       cmp     DWORD [edx],0
-       jne     NEAR ${lbdecor}nocpuid
-       mov     DWORD [edx],1<<10
-       pushfd
-       pop     eax
-       mov     ecx,eax
-       xor     eax,1<<21
-       push    eax
-       popfd
-       pushfd
-       pop     eax
-       xor     eax,ecx
-       bt      eax,21
-       jnc     NEAR ${lbdecor}nocpuid
-       push    ebp
-       push    edi
-       push    ebx
-       mov     edi,edx
-       xor     eax,eax
-       cpuid
-       xor     eax,eax
-       cmp     ebx,'Genu'
-       setne   al
-       mov     ebp,eax
-       cmp     edx,'ineI'
-       setne   al
-       or      ebp,eax
-       cmp     eax,'ntel'
-       setne   al
-       or      ebp,eax
-       mov     eax,1
-       cpuid
-       cmp     ebp,0
-       jne     ${lbdecor}notP4
-       and     ah,15
-       cmp     ah,15
-       jne     ${lbdecor}notP4
-       or      edx,1<<20
-${lbdecor}notP4:
-       bt      edx,28
-       jnc     ${lbdecor}done
-       shr     ebx,16
-       cmp     bl,1
-       ja      ${lbdecor}done
-       and     edx,0xefffffff
-${lbdecor}done:
-       or      edx,1<<10
-       mov     DWORD [edi],edx
-       pop     ebx
-       pop     edi
-       pop     ebp
-${lbdecor}nocpuid:
-       ret
-segment        .CRT\$XCU data align=4
-dd     ${lbdecor}OPENSSL_ia32cap_init
+{   if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out)
+    {  my $comm=<<___;
+${drdecor}segment      .bss
+${drdecor}common       ${nmdecor}OPENSSL_ia32cap_P 4
 ___
-       my $data=<<___;
-segment        .bss
-common ${nmdecor}OPENSSL_ia32cap_P 4
-___
-
-       #<not needed in OpenSSL context>#push (@out,$code);
-
        # comment out OPENSSL_ia32cap_P declarations
        grep {s/(^extern\s+${nmdecor}OPENSSL_ia32cap_P)/\;$1/} @out;
-       push (@out,$data)
+       push (@out,$comm)
     }
     push (@out,$initseg) if ($initseg);                
 }
 
 sub ::comment {   foreach (@_) { push(@out,"\t; $_\n"); }   }
 
-sub islabel    # see is argument is known label
-{ my $i;
-    foreach $i (values %label) { return $i if ($i eq $_[0]); }
-  $label{$_[0]};       # can be undef
-}
-
 sub ::external_label
-{   push(@labels,@_);
-    foreach (@_)
-    {  push(@out, "${drdecor}extern\t${nmdecor}$_\n"); }
-}
+{   push(@out,"${drdecor}extern\t".&::LABEL($_[0],$nmdecor.$_[0])."\n");   }
 
 sub ::public_label
-{   $label{$_[0]}="${nmdecor}${_[0]}" if (!defined($label{$_[0]}));
-    push(@out,"${drdecor}global\t$label{$_[0]}\n");
-}
-
-sub ::label
-{   if (!defined($label{$_[0]}))
-    {  $label{$_[0]}="${lbdecor}${label}${_[0]}"; $label++;   }
-  $label{$_[0]};
-}
-
-sub ::set_label
-{ my $label=&::label($_[0]);
-    &::align($_[1]) if ($_[1]>1);
-    push(@out,"$label{$_[0]}:\n");
-}
+{   push(@out,"${drdecor}global\t".&::LABEL($_[0],$nmdecor.$_[0])."\n");  }
 
 sub ::data_byte
 {   push(@out,(($::mwerks)?".byte\t":"db\t").join(',',@_)."\n");       }
@@ -248,7 +143,7 @@ sub ::picmeup
 }
 
 sub ::initseg
-{ my($f)=$nmdecor.shift;
+{ my $f=$nmdecor.shift;
     if ($::win32)
     {  $initseg=<<___;
 segment        .CRT\$XCU data align=4