summaryrefslogtreecommitdiffstats
path: root/crypto/perlasm/x86nasm.pl
diff options
context:
space:
mode:
authorAndy Polyakov <appro@openssl.org>2007-12-18 09:18:49 +0000
committerAndy Polyakov <appro@openssl.org>2007-12-18 09:18:49 +0000
commit43d8f27dca609666350512bb17a76d39e0c28e70 (patch)
tree05637bfe54675428bb774bb86685e4df853f023e /crypto/perlasm/x86nasm.pl
parentb045299113e6f676b470a20670f077f6e5c10052 (diff)
x86 perlasm overhaul.
Diffstat (limited to 'crypto/perlasm/x86nasm.pl')
-rw-r--r--crypto/perlasm/x86nasm.pl145
1 files changed, 20 insertions, 125 deletions
diff --git a/crypto/perlasm/x86nasm.pl b/crypto/perlasm/x86nasm.pl
index 604f58a2d9..1154f04c34 100644
--- a/crypto/perlasm/x86nasm.pl
+++ b/crypto/perlasm/x86nasm.pl
@@ -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