summaryrefslogtreecommitdiffstats
path: root/lib/libssl/src/crypto/perlasm
diff options
context:
space:
mode:
authordjm <djm@openbsd.org>2008-09-06 12:17:47 +0000
committerdjm <djm@openbsd.org>2008-09-06 12:17:47 +0000
commit4fcf65c5c59fcf6124cf9f1fd81aa546850f974c (patch)
tree3c0b4c46d91bcb87c8eef7a1e84711159b17f71b /lib/libssl/src/crypto/perlasm
parentimport of OpenSSL 0.9.8h (diff)
downloadwireguard-openbsd-4fcf65c5c59fcf6124cf9f1fd81aa546850f974c.tar.xz
wireguard-openbsd-4fcf65c5c59fcf6124cf9f1fd81aa546850f974c.zip
resolve conflicts
Diffstat (limited to 'lib/libssl/src/crypto/perlasm')
-rw-r--r--lib/libssl/src/crypto/perlasm/cbc.pl4
-rw-r--r--lib/libssl/src/crypto/perlasm/x86asm.pl27
-rw-r--r--lib/libssl/src/crypto/perlasm/x86ms.pl122
-rw-r--r--lib/libssl/src/crypto/perlasm/x86nasm.pl153
-rw-r--r--lib/libssl/src/crypto/perlasm/x86unix.pl234
5 files changed, 427 insertions, 113 deletions
diff --git a/lib/libssl/src/crypto/perlasm/cbc.pl b/lib/libssl/src/crypto/perlasm/cbc.pl
index 22149c680ec..e43dc9ae15e 100644
--- a/lib/libssl/src/crypto/perlasm/cbc.pl
+++ b/lib/libssl/src/crypto/perlasm/cbc.pl
@@ -322,7 +322,8 @@ sub cbc
&function_end_A($name);
- &set_label("cbc_enc_jmp_table",1);
+ &align(64);
+ &set_label("cbc_enc_jmp_table");
&data_word("0");
&data_word(&label("ej1")."-".&label("PIC_point"));
&data_word(&label("ej2")."-".&label("PIC_point"));
@@ -341,6 +342,7 @@ sub cbc
#&data_word(&label("dj5")."-".&label("PIC_point"));
#&data_word(&label("dj6")."-".&label("PIC_point"));
#&data_word(&label("dj7")."-".&label("PIC_point"));
+ &align(64);
&function_end_B($name);
diff --git a/lib/libssl/src/crypto/perlasm/x86asm.pl b/lib/libssl/src/crypto/perlasm/x86asm.pl
index c3de90c65d7..f535c9c7fab 100644
--- a/lib/libssl/src/crypto/perlasm/x86asm.pl
+++ b/lib/libssl/src/crypto/perlasm/x86asm.pl
@@ -18,7 +18,7 @@ sub main'asm_init
($type,$fn,$i386)=@_;
$filename=$fn;
- $elf=$cpp=$sol=$aout=$win32=$gaswin=$openbsd=0;
+ $elf=$cpp=$coff=$aout=$win32=$netware=$mwerks=$openbsd=0;
if ( ($type eq "elf"))
{ $elf=1; require "x86unix.pl"; }
elsif ( ($type eq "openbsd-elf"))
@@ -27,28 +27,31 @@ sub main'asm_init
{ $openbsd=1; require "x86unix.pl"; }
elsif ( ($type eq "a.out"))
{ $aout=1; require "x86unix.pl"; }
- elsif ( ($type eq "gaswin"))
- { $gaswin=1; $aout=1; require "x86unix.pl"; }
- elsif ( ($type eq "sol"))
- { $sol=1; require "x86unix.pl"; }
+ elsif ( ($type eq "coff" or $type eq "gaswin"))
+ { $coff=1; require "x86unix.pl"; }
elsif ( ($type eq "cpp"))
{ $cpp=1; require "x86unix.pl"; }
elsif ( ($type eq "win32"))
{ $win32=1; require "x86ms.pl"; }
elsif ( ($type eq "win32n"))
{ $win32=1; require "x86nasm.pl"; }
+ elsif ( ($type eq "nw-nasm"))
+ { $netware=1; require "x86nasm.pl"; }
+ elsif ( ($type eq "nw-mwasm"))
+ { $netware=1; $mwerks=1; require "x86nasm.pl"; }
else
{
print STDERR <<"EOF";
Pick one target type from
- elf - linux, FreeBSD etc
- a.out - old linux
- sol - x86 solaris
- cpp - format so x86unix.cpp can be used
+ elf - Linux, FreeBSD, Solaris x86, etc.
+ a.out - OpenBSD, DJGPP, etc.
+ coff - GAS/COFF such as Win32 targets
win32 - Windows 95/Windows NT
win32n - Windows 95/Windows NT NASM format
openbsd-elf - OpenBSD elf
openbsd-a.out - OpenBSD a.out
+ nw-nasm - NetWare NASM format
+ nw-mwasm- NetWare Metrowerks Assembler
EOF
exit(1);
}
@@ -61,7 +64,7 @@ EOF
&comment("Don't even think of reading this code");
&comment("It was automatically generated by $filename");
&comment("Which is a perl program used to generate the x86 assember for");
-&comment("any of elf, a.out, BSDI, Win32, gaswin (for GNU as on Win32) or Solaris");
+&comment("any of ELF, a.out, COFF, Win32, ...");
&comment("eric <eay\@cryptsoft.com>");
&comment("");
@@ -96,7 +99,7 @@ $tmp
#ifdef OUT
#define OK 1
#define ALIGN 4
-#if defined(__CYGWIN__) || defined(__DJGPP__) || defined(__MINGW32__)
+#if defined(__CYGWIN__) || defined(__DJGPP__) || (__MINGW32__)
#undef SIZE
#undef TYPE
#define SIZE(a,b)
@@ -130,6 +133,4 @@ BSDI - a.out with a very primative version of as.
EOF
}
-sub main'align() {} # swallow align statements in 0.9.7 context
-
1;
diff --git a/lib/libssl/src/crypto/perlasm/x86ms.pl b/lib/libssl/src/crypto/perlasm/x86ms.pl
index b6bd744057e..a0be2934c20 100644
--- a/lib/libssl/src/crypto/perlasm/x86ms.pl
+++ b/lib/libssl/src/crypto/perlasm/x86ms.pl
@@ -27,7 +27,13 @@ $label="L000";
sub main'asm_init_output { @out=(); }
sub main'asm_get_output { return(@out); }
sub main'get_labels { return(@labels); }
-sub main'external_label { push(@labels,@_); }
+sub main'external_label
+{
+ push(@labels,@_);
+ foreach (@_) {
+ push(@out, "EXTRN\t_$_:DWORD\n");
+ }
+}
sub main'LB
{
@@ -51,6 +57,11 @@ sub main'DWP
&get_mem("DWORD",@_);
}
+sub main'QWP
+ {
+ &get_mem("QWORD",@_);
+ }
+
sub main'BC
{
return @_;
@@ -87,7 +98,7 @@ sub get_mem
$reg2=&conv($1);
$addr="_$2";
}
- elsif ($addr =~ /^[_a-zA-Z]/)
+ elsif ($addr =~ /^[_a-z][_a-z0-9]*$/i)
{
$addr="_$addr";
}
@@ -128,12 +139,14 @@ sub main'xorb { &out2("xor",@_); }
sub main'add { &out2("add",@_); }
sub main'adc { &out2("adc",@_); }
sub main'sub { &out2("sub",@_); }
+sub main'sbb { &out2("sbb",@_); }
sub main'rotl { &out2("rol",@_); }
sub main'rotr { &out2("ror",@_); }
sub main'exch { &out2("xchg",@_); }
sub main'cmp { &out2("cmp",@_); }
sub main'lea { &out2("lea",@_); }
sub main'mul { &out1("mul",@_); }
+sub main'imul { &out2("imul",@_); }
sub main'div { &out1("div",@_); }
sub main'dec { &out1("dec",@_); }
sub main'inc { &out1("inc",@_); }
@@ -155,26 +168,54 @@ sub main'jne { &out1("jne",@_); }
sub main'jno { &out1("jno",@_); }
sub main'push { &out1("push",@_); $stack+=4; }
sub main'pop { &out1("pop",@_); $stack-=4; }
+sub main'pushf { &out0("pushfd"); $stack+=4; }
+sub main'popf { &out0("popfd"); $stack-=4; }
sub main'bswap { &out1("bswap",@_); &using486(); }
sub main'not { &out1("not",@_); }
sub main'call { &out1("call",($_[0]=~/^\$L/?'':'_').$_[0]); }
+sub main'call_ptr { &out1p("call",@_); }
sub main'ret { &out0("ret"); }
sub main'nop { &out0("nop"); }
+sub main'test { &out2("test",@_); }
+sub main'bt { &out2("bt",@_); }
+sub main'leave { &out0("leave"); }
+sub main'cpuid { &out0("DW\t0A20Fh"); }
+sub main'rdtsc { &out0("DW\t0310Fh"); }
+sub main'halt { &out0("hlt"); }
sub main'movz { &out2("movzx",@_); }
+sub main'neg { &out1("neg",@_); }
+sub main'cld { &out0("cld"); }
+
+# SSE2
+sub main'emms { &out0("emms"); }
+sub main'movd { &out2("movd",@_); }
+sub main'movq { &out2("movq",@_); }
+sub main'movdqu { &out2("movdqu",@_); }
+sub main'movdqa { &out2("movdqa",@_); }
+sub main'movdq2q{ &out2("movdq2q",@_); }
+sub main'movq2dq{ &out2("movq2dq",@_); }
+sub main'paddq { &out2("paddq",@_); }
+sub main'pmuludq{ &out2("pmuludq",@_); }
+sub main'psrlq { &out2("psrlq",@_); }
+sub main'psllq { &out2("psllq",@_); }
+sub main'pxor { &out2("pxor",@_); }
+sub main'por { &out2("por",@_); }
+sub main'pand { &out2("pand",@_); }
sub out2
{
local($name,$p1,$p2)=@_;
- local($l,$t);
+ local($l,$t,$line);
- push(@out,"\t$name\t");
+ $line="\t$name\t";
$t=&conv($p1).",";
$l=length($t);
- push(@out,$t);
+ $line.="$t";
$l=4-($l+9)/8;
- push(@out,"\t" x $l);
- push(@out,&conv($p2));
- push(@out,"\n");
+ $line.="\t" x $l;
+ $line.=&conv($p2);
+ if ($line=~/\bxmm[0-7]\b/i) { $line=~s/\b[A-Z]+WORD\s+PTR/XMMWORD PTR/i; }
+ push(@out,$line."\n");
}
sub out0
@@ -214,7 +255,9 @@ sub main'file
local($tmp)=<<"EOF";
TITLE $file.asm
.386
-.model FLAT
+.model FLAT
+_TEXT\$ SEGMENT PAGE 'CODE'
+
EOF
push(@out,$tmp);
}
@@ -226,7 +269,6 @@ sub main'function_begin
push(@labels,$func);
local($tmp)=<<"EOF";
-_TEXT SEGMENT
PUBLIC _$func
$extra
_$func PROC NEAR
@@ -244,7 +286,6 @@ sub main'function_begin_B
local($func,$extra)=@_;
local($tmp)=<<"EOF";
-_TEXT SEGMENT
PUBLIC _$func
$extra
_$func PROC NEAR
@@ -264,7 +305,6 @@ sub main'function_end
pop ebp
ret
_$func ENDP
-_TEXT ENDS
EOF
push(@out,$tmp);
$stack=0;
@@ -277,7 +317,6 @@ sub main'function_end_B
local($tmp)=<<"EOF";
_$func ENDP
-_TEXT ENDS
EOF
push(@out,$tmp);
$stack=0;
@@ -300,6 +339,20 @@ EOF
sub main'file_end
{
+ # try to detect if SSE2 or MMX extensions were used...
+ my $xmmheader=<<___;
+.686
+.XMM
+IF \@Version LT 800
+XMMWORD STRUCT 16
+ DQ 2 dup (?)
+XMMWORD ENDS
+ENDIF
+___
+ if (grep {/\b[x]?mm[0-7]\b/i} @out) {
+ grep {s/\.[3-7]86/$xmmheader/} @out;
+ }
+ push(@out,"_TEXT\$ ENDS\n");
push(@out,"END\n");
}
@@ -331,6 +384,12 @@ sub main'comment
}
}
+sub main'public_label
+ {
+ $label{$_[0]}="_$_[0]" if (!defined($label{$_[0]}));
+ push(@out,"PUBLIC\t$label{$_[0]}\n");
+ }
+
sub main'label
{
if (!defined($label{$_[0]}))
@@ -348,19 +407,37 @@ sub main'set_label
$label{$_[0]}="\$${label}${_[0]}";
$label++;
}
+ if ($_[1]!=0 && $_[1]>1)
+ {
+ main'align($_[1]);
+ }
if((defined $_[2]) && ($_[2] == 1))
{
push(@out,"$label{$_[0]}::\n");
}
+ elsif ($label{$_[0]} !~ /^\$/)
+ {
+ push(@out,"$label{$_[0]}\tLABEL PTR\n");
+ }
else
{
push(@out,"$label{$_[0]}:\n");
}
}
+sub main'data_byte
+ {
+ push(@out,"\tDB\t".join(',',@_)."\n");
+ }
+
sub main'data_word
{
- push(@out,"\tDD\t$_[0]\n");
+ push(@out,"\tDD\t".join(',',@_)."\n");
+ }
+
+sub main'align
+ {
+ push(@out,"\tALIGN\t$_[0]\n");
}
sub out1p
@@ -368,7 +445,7 @@ sub out1p
local($name,$p1)=@_;
local($l,$t);
- push(@out,"\t$name\t ".&conv($p1)."\n");
+ push(@out,"\t$name\t".&conv($p1)."\n");
}
sub main'picmeup
@@ -378,3 +455,18 @@ sub main'picmeup
}
sub main'blindpop { &out1("pop",@_); }
+
+sub main'initseg
+ {
+ local($f)=@_;
+ local($tmp)=<<___;
+OPTION DOTNAME
+.CRT\$XCU SEGMENT DWORD PUBLIC 'DATA'
+EXTRN _$f:NEAR
+DD _$f
+.CRT\$XCU ENDS
+___
+ push(@out,$tmp);
+ }
+
+1;
diff --git a/lib/libssl/src/crypto/perlasm/x86nasm.pl b/lib/libssl/src/crypto/perlasm/x86nasm.pl
index 4bdb3fe1809..fa38f89c09f 100644
--- a/lib/libssl/src/crypto/perlasm/x86nasm.pl
+++ b/lib/libssl/src/crypto/perlasm/x86nasm.pl
@@ -3,6 +3,7 @@
package x86nasm;
$label="L000";
+$under=($main'netware)?'':'_';
%lb=( 'eax', 'al',
'ebx', 'bl',
@@ -32,7 +33,8 @@ sub main'external_label
{
push(@labels,@_);
foreach (@_) {
- push(@out, "extern\t_$_\n");
+ push(@out,".") if ($main'mwerks);
+ push(@out, "extern\t${under}$_\n");
}
}
@@ -58,14 +60,19 @@ sub main'DWP
&get_mem("DWORD",@_);
}
+sub main'QWP
+ {
+ &get_mem("",@_);
+ }
+
sub main'BC
{
- return "BYTE @_";
+ return (($main'mwerks)?"":"BYTE ")."@_";
}
sub main'DWC
{
- return "DWORD @_";
+ return (($main'mwerks)?"":"DWORD ")."@_";
}
sub main'stack_push
@@ -86,16 +93,22 @@ sub get_mem
{
my($size,$addr,$reg1,$reg2,$idx)=@_;
my($t,$post);
- my($ret)="$size [";
+ my($ret)=$size;
+ if ($ret ne "")
+ {
+ $ret .= " PTR" if ($main'mwerks);
+ $ret .= " ";
+ }
+ $ret .= "[";
$addr =~ s/^\s+//;
if ($addr =~ /^(.+)\+(.+)$/)
{
$reg2=&conv($1);
- $addr="_$2";
+ $addr="$under$2";
}
- elsif ($addr =~ /^[_a-zA-Z]/)
+ elsif ($addr =~ /^[_a-z][_a-z0-9]*$/i)
{
- $addr="_$addr";
+ $addr="$under$addr";
}
if ($addr =~ /^.+\-.+$/) { $addr="($addr)"; }
@@ -134,12 +147,14 @@ sub main'xorb { &out2("xor",@_); }
sub main'add { &out2("add",@_); }
sub main'adc { &out2("adc",@_); }
sub main'sub { &out2("sub",@_); }
+sub main'sbb { &out2("sbb",@_); }
sub main'rotl { &out2("rol",@_); }
sub main'rotr { &out2("ror",@_); }
sub main'exch { &out2("xchg",@_); }
sub main'cmp { &out2("cmp",@_); }
sub main'lea { &out2("lea",@_); }
sub main'mul { &out1("mul",@_); }
+sub main'imul { &out2("imul",@_); }
sub main'div { &out1("div",@_); }
sub main'dec { &out1("dec",@_); }
sub main'inc { &out1("inc",@_); }
@@ -147,29 +162,57 @@ sub main'jmp { &out1("jmp",@_); }
sub main'jmp_ptr { &out1p("jmp",@_); }
# This is a bit of a kludge: declare all branches as NEAR.
-sub main'je { &out1("je NEAR",@_); }
-sub main'jle { &out1("jle NEAR",@_); }
-sub main'jz { &out1("jz NEAR",@_); }
-sub main'jge { &out1("jge NEAR",@_); }
-sub main'jl { &out1("jl NEAR",@_); }
-sub main'ja { &out1("ja NEAR",@_); }
-sub main'jae { &out1("jae NEAR",@_); }
-sub main'jb { &out1("jb NEAR",@_); }
-sub main'jbe { &out1("jbe NEAR",@_); }
-sub main'jc { &out1("jc NEAR",@_); }
-sub main'jnc { &out1("jnc NEAR",@_); }
-sub main'jnz { &out1("jnz NEAR",@_); }
-sub main'jne { &out1("jne NEAR",@_); }
-sub main'jno { &out1("jno NEAR",@_); }
+$near=($main'mwerks)?'':'NEAR';
+sub main'je { &out1("je $near",@_); }
+sub main'jle { &out1("jle $near",@_); }
+sub main'jz { &out1("jz $near",@_); }
+sub main'jge { &out1("jge $near",@_); }
+sub main'jl { &out1("jl $near",@_); }
+sub main'ja { &out1("ja $near",@_); }
+sub main'jae { &out1("jae $near",@_); }
+sub main'jb { &out1("jb $near",@_); }
+sub main'jbe { &out1("jbe $near",@_); }
+sub main'jc { &out1("jc $near",@_); }
+sub main'jnc { &out1("jnc $near",@_); }
+sub main'jnz { &out1("jnz $near",@_); }
+sub main'jne { &out1("jne $near",@_); }
+sub main'jno { &out1("jno $near",@_); }
sub main'push { &out1("push",@_); $stack+=4; }
sub main'pop { &out1("pop",@_); $stack-=4; }
+sub main'pushf { &out0("pushfd"); $stack+=4; }
+sub main'popf { &out0("popfd"); $stack-=4; }
sub main'bswap { &out1("bswap",@_); &using486(); }
sub main'not { &out1("not",@_); }
-sub main'call { &out1("call",($_[0]=~/^\$L/?'':'_').$_[0]); }
+sub main'call { &out1("call",($_[0]=~/^\@L/?'':$under).$_[0]); }
+sub main'call_ptr { &out1p("call",@_); }
sub main'ret { &out0("ret"); }
sub main'nop { &out0("nop"); }
+sub main'test { &out2("test",@_); }
+sub main'bt { &out2("bt",@_); }
+sub main'leave { &out0("leave"); }
+sub main'cpuid { &out0("cpuid"); }
+sub main'rdtsc { &out0("rdtsc"); }
+sub main'halt { &out0("hlt"); }
sub main'movz { &out2("movzx",@_); }
+sub main'neg { &out1("neg",@_); }
+sub main'cld { &out0("cld"); }
+
+# SSE2
+sub main'emms { &out0("emms"); }
+sub main'movd { &out2("movd",@_); }
+sub main'movq { &out2("movq",@_); }
+sub main'movdqu { &out2("movdqu",@_); }
+sub main'movdqa { &out2("movdqa",@_); }
+sub main'movdq2q{ &out2("movdq2q",@_); }
+sub main'movq2dq{ &out2("movq2dq",@_); }
+sub main'paddq { &out2("paddq",@_); }
+sub main'pmuludq{ &out2("pmuludq",@_); }
+sub main'psrlq { &out2("psrlq",@_); }
+sub main'psllq { &out2("psllq",@_); }
+sub main'pxor { &out2("pxor",@_); }
+sub main'por { &out2("por",@_); }
+sub main'pand { &out2("pand",@_); }
sub out2
{
@@ -177,7 +220,7 @@ sub out2
my($l,$t);
push(@out,"\t$name\t");
- if ($name eq "lea")
+ if (!$main'mwerks and $name eq "lea")
{
$p1 =~ s/^[^\[]*\[/\[/;
$p2 =~ s/^[^\[]*\[/\[/;
@@ -221,15 +264,17 @@ sub using486
sub main'file
{
- local $tmp;
- $tmp=<<___;
+ if ($main'mwerks) { push(@out,".section\t.text\n"); }
+ else {
+ local $tmp=<<___;
%ifdef __omf__
section code use32 class=code
%else
section .text
%endif
___
- push(@out,$tmp);
+ push(@out,$tmp);
+ }
}
sub main'function_begin
@@ -237,9 +282,10 @@ sub main'function_begin
my($func,$extra)=@_;
push(@labels,$func);
+ push(@out,".") if ($main'mwerks);
my($tmp)=<<"EOF";
-global _$func
-_$func:
+global $under$func
+$under$func:
push ebp
push ebx
push esi
@@ -252,9 +298,10 @@ EOF
sub main'function_begin_B
{
my($func,$extra)=@_;
+ push(@out,".") if ($main'mwerks);
my($tmp)=<<"EOF";
-global _$func
-_$func:
+global $under$func
+$under$func:
EOF
push(@out,$tmp);
$stack=4;
@@ -328,11 +375,18 @@ sub main'comment
}
}
+sub main'public_label
+ {
+ $label{$_[0]}="${under}${_[0]}" if (!defined($label{$_[0]}));
+ push(@out,".") if ($main'mwerks);
+ push(@out,"global\t$label{$_[0]}\n");
+ }
+
sub main'label
{
if (!defined($label{$_[0]}))
{
- $label{$_[0]}="\$${label}${_[0]}";
+ $label{$_[0]}="\@${label}${_[0]}";
$label++;
}
return($label{$_[0]});
@@ -342,15 +396,30 @@ sub main'set_label
{
if (!defined($label{$_[0]}))
{
- $label{$_[0]}="\$${label}${_[0]}";
+ $label{$_[0]}="\@${label}${_[0]}";
$label++;
}
+ if ($_[1]!=0 && $_[1]>1)
+ {
+ main'align($_[1]);
+ }
push(@out,"$label{$_[0]}:\n");
}
+sub main'data_byte
+ {
+ push(@out,(($main'mwerks)?".byte\t":"DB\t").join(',',@_)."\n");
+ }
+
sub main'data_word
{
- push(@out,"\tDD\t$_[0]\n");
+ push(@out,(($main'mwerks)?".long\t":"DD\t").join(',',@_)."\n");
+ }
+
+sub main'align
+ {
+ push(@out,".") if ($main'mwerks);
+ push(@out,"align\t$_[0]\n");
}
sub out1p
@@ -358,7 +427,7 @@ sub out1p
my($name,$p1)=@_;
my($l,$t);
- push(@out,"\t$name\t ".&conv($p1)."\n");
+ push(@out,"\t$name\t".&conv($p1)."\n");
}
sub main'picmeup
@@ -368,3 +437,19 @@ sub main'picmeup
}
sub main'blindpop { &out1("pop",@_); }
+
+sub main'initseg
+ {
+ local($f)=@_;
+ if ($main'win32)
+ {
+ local($tmp)=<<___;
+segment .CRT\$XCU data
+extern $under$f
+DD $under$f
+___
+ push(@out,$tmp);
+ }
+ }
+
+1;
diff --git a/lib/libssl/src/crypto/perlasm/x86unix.pl b/lib/libssl/src/crypto/perlasm/x86unix.pl
index b61425e9519..02d72a32bcd 100644
--- a/lib/libssl/src/crypto/perlasm/x86unix.pl
+++ b/lib/libssl/src/crypto/perlasm/x86unix.pl
@@ -1,14 +1,15 @@
#!/usr/local/bin/perl
-package x86unix;
+package x86unix; # GAS actually...
$label="L000";
$const="";
$constl=0;
$align=($main'aout)?"4":"16";
-$under=($main'aout)?"_":"";
-$com_start=($main'sol)?"/":"#";
+$under=($main'aout or $main'coff)?"_":"";
+$dot=($main'aout)?"":".";
+$com_start="#" if ($main'aout or $main'coff);
sub main'asm_init_output { @out=(); }
sub main'asm_get_output { return(@out); }
@@ -57,6 +58,24 @@ if ($main'cpp)
'edi', '%edi',
'ebp', '%ebp',
'esp', '%esp',
+
+ 'mm0', '%mm0',
+ 'mm1', '%mm1',
+ 'mm2', '%mm2',
+ 'mm3', '%mm3',
+ 'mm4', '%mm4',
+ 'mm5', '%mm5',
+ 'mm6', '%mm6',
+ 'mm7', '%mm7',
+
+ 'xmm0', '%xmm0',
+ 'xmm1', '%xmm1',
+ 'xmm2', '%xmm2',
+ 'xmm3', '%xmm3',
+ 'xmm4', '%xmm4',
+ 'xmm5', '%xmm5',
+ 'xmm6', '%xmm6',
+ 'xmm7', '%xmm7',
);
%reg_val=(
@@ -103,6 +122,11 @@ sub main'DWP
return($ret);
}
+sub main'QWP
+ {
+ return(&main'DWP(@_));
+ }
+
sub main'BP
{
return(&main'DWP(@_));
@@ -146,12 +170,14 @@ sub main'xorb { &out2("xorb",@_); }
sub main'add { &out2($_[0]=~/%[a-d][lh]/?"addb":"addl",@_); }
sub main'adc { &out2("adcl",@_); }
sub main'sub { &out2("subl",@_); }
+sub main'sbb { &out2("sbbl",@_); }
sub main'rotl { &out2("roll",@_); }
sub main'rotr { &out2("rorl",@_); }
sub main'exch { &out2($_[0]=~/%[a-d][lh]/?"xchgb":"xchgl",@_); }
sub main'cmp { &out2("cmpl",@_); }
sub main'lea { &out2("leal",@_); }
sub main'mul { &out1("mull",@_); }
+sub main'imul { &out2("imull",@_); }
sub main'div { &out1("divl",@_); }
sub main'jmp { &out1("jmp",@_); }
sub main'jmp_ptr { &out1p("jmp",@_); }
@@ -173,15 +199,48 @@ sub main'dec { &out1("decl",@_); }
sub main'inc { &out1($_[0]=~/%[a-d][hl]/?"incb":"incl",@_); }
sub main'push { &out1("pushl",@_); $stack+=4; }
sub main'pop { &out1("popl",@_); $stack-=4; }
-sub main'pushf { &out0("pushf"); $stack+=4; }
-sub main'popf { &out0("popf"); $stack-=4; }
+sub main'pushf { &out0("pushfl"); $stack+=4; }
+sub main'popf { &out0("popfl"); $stack-=4; }
sub main'not { &out1("notl",@_); }
-sub main'call { &out1("call",($_[0]=~/^\.L/?'':$under).$_[0]); }
+sub main'call { my $pre=$under;
+ foreach $i (%label)
+ { if ($label{$i} eq $_[0]) { $pre=''; last; } }
+ &out1("call",$pre.$_[0]);
+ }
+sub main'call_ptr { &out1p("call",@_); }
sub main'ret { &out0("ret"); }
sub main'nop { &out0("nop"); }
-sub main'test { &out2("testl",@_); }
+sub main'test { &out2("testl",@_); }
+sub main'bt { &out2("btl",@_); }
+sub main'leave { &out0("leave"); }
+sub main'cpuid { &out0(".byte\t0x0f,0xa2"); }
+sub main'rdtsc { &out0(".byte\t0x0f,0x31"); }
+sub main'halt { &out0("hlt"); }
sub main'movz { &out2("movzbl",@_); }
-sub main'neg { &out1("negl",@_); }
+sub main'neg { &out1("negl",@_); }
+sub main'cld { &out0("cld"); }
+
+# SSE2
+sub main'emms { &out0("emms"); }
+sub main'movd { &out2("movd",@_); }
+sub main'movdqu { &out2("movdqu",@_); }
+sub main'movdqa { &out2("movdqa",@_); }
+sub main'movdq2q{ &out2("movdq2q",@_); }
+sub main'movq2dq{ &out2("movq2dq",@_); }
+sub main'paddq { &out2("paddq",@_); }
+sub main'pmuludq{ &out2("pmuludq",@_); }
+sub main'psrlq { &out2("psrlq",@_); }
+sub main'psllq { &out2("psllq",@_); }
+sub main'pxor { &out2("pxor",@_); }
+sub main'por { &out2("por",@_); }
+sub main'pand { &out2("pand",@_); }
+sub main'movq {
+ local($p1,$p2,$optimize)=@_;
+ if ($optimize && $p1=~/^mm[0-7]$/ && $p2=~/^mm[0-7]$/)
+ # movq between mmx registers can sink Intel CPUs
+ { push(@out,"\tpshufw\t\$0xe4,%$p2,%$p1\n"); }
+ else { &out2("movq",@_); }
+ }
# The bswapl instruction is new for the 486. Emulate if i386.
sub main'bswap
@@ -290,8 +349,6 @@ sub main'file
local($tmp)=<<"EOF";
.file "$file.s"
- .version "01.01"
-gcc2_compiled.:
EOF
push(@out,$tmp);
}
@@ -308,15 +365,17 @@ sub main'function_begin
local($tmp)=<<"EOF";
.text
- .align $align
-.globl $func
+.globl $func
EOF
push(@out,$tmp);
if ($main'cpp)
- { $tmp=push(@out,"\tTYPE($func,\@function)\n"); }
- elsif ($main'gaswin)
- { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
- else { $tmp=push(@out,"\t.type\t$func,\@function\n"); }
+ { $tmp=push(@out,"TYPE($func,\@function)\n"); }
+ elsif ($main'coff)
+ { $tmp=push(@out,".def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
+ elsif ($main'aout and !$main'pic)
+ { }
+ else { $tmp=push(@out,".type\t$func,\@function\n"); }
+ push(@out,".align\t$align\n");
push(@out,"$func:\n");
skip:
$tmp=<<"EOF";
@@ -342,15 +401,17 @@ sub main'function_begin_B
local($tmp)=<<"EOF";
.text
- .align $align
-.globl $func
+.globl $func
EOF
push(@out,$tmp);
if ($main'cpp)
- { push(@out,"\tTYPE($func,\@function)\n"); }
- elsif ($main'gaswin)
- { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
- else { push(@out,"\t.type $func,\@function\n"); }
+ { push(@out,"TYPE($func,\@function)\n"); }
+ elsif ($main'coff)
+ { $tmp=push(@out,".def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
+ elsif ($main'aout and !$main'pic)
+ { }
+ else { push(@out,".type $func,\@function\n"); }
+ push(@out,".align\t$align\n");
push(@out,"$func:\n");
skip:
$stack=4;
@@ -368,15 +429,15 @@ sub main'function_end
popl %ebx
popl %ebp
ret
-.L_${func}_end:
+${dot}L_${func}_end:
EOF
push(@out,$tmp);
if ($main'cpp)
- { push(@out,"\tSIZE($func,.L_${func}_end-$func)\n"); }
- elsif ($main'gaswin)
- { $tmp=push(@out,"\t.align 4\n"); }
- else { push(@out,"\t.size\t$func,.L_${func}_end-$func\n"); }
+ { push(@out,"SIZE($func,${dot}L_${func}_end-$func)\n"); }
+ elsif ($main'coff or $main'aout)
+ { }
+ else { push(@out,".size\t$func,${dot}L_${func}_end-$func\n"); }
push(@out,".ident \"$func\"\n");
$stack=0;
%label=();
@@ -402,13 +463,13 @@ sub main'function_end_B
$func=$under.$func;
- push(@out,".L_${func}_end:\n");
+ push(@out,"${dot}L_${func}_end:\n");
if ($main'cpp)
- { push(@out,"\tSIZE($func,.L_${func}_end-$func)\n"); }
- elsif ($main'gaswin)
- { push(@out,"\t.align 4\n"); }
- else { push(@out,"\t.size\t$func,.L_${func}_end-$func\n"); }
- push(@out,".ident \"desasm.pl\"\n");
+ { push(@out,"SIZE($func,${dot}L_${func}_end-$func)\n"); }
+ elsif ($main'coff or $main'aout)
+ { }
+ else { push(@out,".size\t$func,${dot}L_${func}_end-$func\n"); }
+ push(@out,".ident \"$func\"\n");
$stack=0;
%label=();
}
@@ -449,10 +510,10 @@ sub main'swtmp
sub main'comment
{
- if (!$main'openbsd && $main'elf)
+ if (!defined($com_start) or $main'elf)
+ { # Regarding $main'elf above...
# GNU and SVR4 as'es use different comment delimiters,
- { # so we just skip comments...
- push(@out,"\n");
+ push(@out,"\n"); # so we just skip ELF comments...
return;
}
foreach (@_)
@@ -465,16 +526,16 @@ sub main'comment
}
sub main'public_label
- {
- $label{$_[0]}="${under}${_[0]}" if (!defined($label{$_[0]}));
- push(@out,".globl\t$label{$_[0]}\n");
- }
+ {
+ $label{$_[0]}="${under}${_[0]}" if (!defined($label{$_[0]}));
+ push(@out,".globl\t$label{$_[0]}\n");
+ }
sub main'label
{
if (!defined($label{$_[0]}))
{
- $label{$_[0]}=".${label}${_[0]}";
+ $label{$_[0]}="${dot}${label}${_[0]}";
$label++;
}
return($label{$_[0]});
@@ -484,18 +545,35 @@ sub main'set_label
{
if (!defined($label{$_[0]}))
{
- $label{$_[0]}=".${label}${_[0]}";
+ $label{$_[0]}="${dot}${label}${_[0]}";
$label++;
}
- if ($main'openbsd)
- { push(@out,"_ALIGN_TEXT\n") if ($_[1] != 0); }
- else
- { push(@out,".align $align\n") if ($_[1] != 0); }
+ if ($_[1]!=0)
+ {
+ if ($_[1]>1) { main'align($_[1]); }
+ else
+ {
+ if ($main'openbsd)
+ { push(@out,"_ALIGN_TEXT\n"); }
+ else
+ { push(@out,".align $align\n"); }
+ }
+ }
push(@out,"$label{$_[0]}:\n");
}
sub main'file_end
{
+ # try to detect if SSE2 or MMX extensions were used on ELF platform...
+ if ($main'elf && grep {/\b%[x]*mm[0-7]\b|OPENSSL_ia32cap_P\b/i} @out) {
+ local($tmp);
+
+ push (@out,"\n.section\t.bss\n");
+ push (@out,".comm\t${under}OPENSSL_ia32cap_P,4,4\n");
+
+ return;
+ }
+
if ($const ne "")
{
push(@out,".section .rodata\n");
@@ -504,11 +582,31 @@ sub main'file_end
}
}
+sub main'data_byte
+ {
+ push(@out,"\t.byte\t".join(',',@_)."\n");
+ }
+
sub main'data_word
{
push(@out,"\t.long\t".join(',',@_)."\n");
}
+sub main'align
+ {
+ my $val=$_[0],$p2,$i;
+ if ($main'aout) {
+ for ($p2=0;$val!=0;$val>>=1) { $p2++; }
+ $val=$p2-1;
+ $val.=",0x90";
+ }
+ push(@out,".align\t$val\n");
+ if ($main'openbsd)
+ { push(@out,"_ALIGN_TEXT\n"); }
+ else
+ { push(@out,".align $tval\n"); }
+ }
+
# debug output functions: puts, putx, printf
sub main'puts
@@ -588,7 +686,6 @@ sub main'picmeup
{
local($tmp)=<<___;
#if (defined(ELF) || defined(SOL)) && defined(PIC)
- .align 8
call 1f
1: popl $regs{$dst}
addl \$_GLOBAL_OFFSET_TABLE_+[.-1b],$regs{$dst}
@@ -611,13 +708,12 @@ ___
}
elsif ($main'pic && ($main'elf || $main'aout))
{
- push(@out,"\t.align\t8\n");
&main'call(&main'label("PIC_me_up"));
&main'set_label("PIC_me_up");
&main'blindpop($dst);
- &main'add($dst,"\$$under"."_GLOBAL_OFFSET_TABLE_+[.-".
+ &main'add($dst,"\$${under}_GLOBAL_OFFSET_TABLE_+[.-".
&main'label("PIC_me_up") . "]");
- &main'mov($dst,&main'DWP($sym."\@GOT",$dst));
+ &main'mov($dst,&main'DWP($under.$sym."\@GOT",$dst));
}
else
{
@@ -626,3 +722,41 @@ ___
}
sub main'blindpop { &out1("popl",@_); }
+
+sub main'initseg
+ {
+ local($f)=@_;
+ local($tmp);
+ if ($main'elf)
+ {
+ $tmp=<<___;
+.section .init
+ call $under$f
+ jmp .Linitalign
+.align $align
+.Linitalign:
+___
+ }
+ elsif ($main'coff)
+ {
+ $tmp=<<___; # applies to both Cygwin and Mingw
+.section .ctors
+.long $under$f
+___
+ }
+ elsif ($main'aout)
+ {
+ local($ctor)="${under}_GLOBAL_\$I\$$f";
+ $tmp=".text\n";
+ $tmp.=".type $ctor,\@function\n" if ($main'pic);
+ $tmp.=<<___; # OpenBSD way...
+.globl $ctor
+.align 2
+$ctor:
+ jmp $under$f
+___
+ }
+ push(@out,$tmp) if ($tmp);
+ }
+
+1;