ppc-xlate.pl: get linux64 declaration right.
[openssl.git] / crypto / perlasm / x86_64-xlate.pl
index 4f68e90ca2c98d56d13e10d5f46f5ca07d19d05e..61d77d941e8ec4a59edb946bffe848b293315f63 100755 (executable)
@@ -121,7 +121,7 @@ my %globals;
                $self->{sz} = "b";
            } elsif ($self->{op} =~ /call|jmp/) {
                $self->{sz} = "";
-           } elsif ($self->{op} =~ /^p/ && $' !~ /^(ush|op)/) { # SSEn
+           } elsif ($self->{op} =~ /^p/ && $' !~ /^(ush|op|insrw)/) { # SSEn
                $self->{sz} = "";
            } elsif ($self->{op} =~ /([a-z]{3,})([qlwb])$/) {
                $self->{op} = $1;
@@ -167,7 +167,7 @@ my %globals;
            } elsif ($self->{op} =~ /^(pop|push)f/) {
                $self->{op} .= $self->{sz};
            } elsif ($self->{op} eq "call" && $current_segment eq ".CRT\$XCU") {
-               $self->{op} = "ALIGN\t8\n\tDQ";
+               $self->{op} = "\tDQ";
            } 
            $self->{op};
        }
@@ -256,15 +256,16 @@ my %globals;
            $self->{label} =~ s/^___imp_/__imp__/   if ($flavour eq "mingw64");
 
            if (defined($self->{index})) {
-               sprintf "%s%s(%%%s,%%%s,%d)",$self->{asterisk},
-                                       $self->{label},$self->{base},
+               sprintf "%s%s(%s,%%%s,%d)",$self->{asterisk},
+                                       $self->{label},
+                                       $self->{base}?"%$self->{base}":"",
                                        $self->{index},$self->{scale};
            } else {
                sprintf "%s%s(%%%s)",   $self->{asterisk},$self->{label},$self->{base};
            }
        } else {
            %szmap = (  b=>"BYTE$PTR", w=>"WORD$PTR", l=>"DWORD$PTR",
-                       q=>"QWORD$PTR",o=>"OWORD$PTR" );
+                       q=>"QWORD$PTR",o=>"OWORD$PTR",x=>"XMMWORD$PTR" );
 
            $self->{label} =~ s/\./\$/g;
            $self->{label} =~ s/(?<![\w\$\.])0x([0-9a-f]+)/0$1h/ig;
@@ -272,10 +273,10 @@ my %globals;
            $sz="q" if ($self->{asterisk});
 
            if (defined($self->{index})) {
-               sprintf "%s[%s%s*%d+%s]",$szmap{$sz},
+               sprintf "%s[%s%s*%d%s]",$szmap{$sz},
                                        $self->{label}?"$self->{label}+":"",
                                        $self->{index},$self->{scale},
-                                       $self->{base};
+                                       $self->{base}?"+$self->{base}":"";
            } elsif ($self->{base} eq "rip") {
                sprintf "%s[%s]",$szmap{$sz},$self->{label};
            } else {
@@ -546,6 +547,8 @@ my %globals;
                                        if ($line=~/\.([px])data/) {
                                            $v.=" rdata align=";
                                            $v.=$1 eq "p"? 4 : 8;
+                                       } elsif ($line=~/\.CRT\$/i) {
+                                           $v.=" rdata align=8";
                                        }
                                    } else {
                                        $v="$current_segment\tENDS\n" if ($current_segment);
@@ -553,6 +556,8 @@ my %globals;
                                        if ($line=~/\.([px])data/) {
                                            $v.=" READONLY";
                                            $v.=" ALIGN(".($1 eq "p" ? 4 : 8).")" if ($masm>=$masmref);
+                                       } elsif ($line=~/\.CRT\$/i) {
+                                           $v.=" READONLY DWORD";
                                        }
                                    }
                                    $current_segment = $line;
@@ -634,62 +639,89 @@ sub rex {
    }
 }
 
-# older gas doesn't handle SSE>2 instructions
+# older gas and ml64 don't handle SSE>2 instructions
 my %regrm = (  "%eax"=>0, "%ecx"=>1, "%edx"=>2, "%ebx"=>3,
                "%esp"=>4, "%ebp"=>5, "%esi"=>6, "%edi"=>7      );
 
 my $pextrd = sub {
-  my ($imm,$src,$dst) = @_;
-    if ("$imm:$src" =~ /\$([0-9]+):%xmm([0-9]+)/) {
+    if (shift =~ /\$([0-9]+),%xmm([0-9]+),(%\w+)/) {
       my @opcode=(0x66);
        $imm=$1;
        $src=$2;
+       $dst=$3;
        if ($dst =~ /%r([0-9]+)d/)      { $dst = $1; }
        elsif ($dst =~ /%e/)            { $dst = $regrm{$dst}; }
        rex(\@opcode,$src,$dst);
        push @opcode,0x0f,0x3a,0x16;
        push @opcode,0xc0|(($src&7)<<3)|($dst&7);       # ModR/M
        push @opcode,$imm;
-       printf "\t.byte\t%s\n",join(',',@opcode);
+       @opcode;
     } else {
-       printf "\tpextrd\t%s\n",join(',',@_);
+       ();
     }
-} if ($gas);
+};
 
 my $pinsrd = sub {
-  my ($imm,$src,$dst) = @_;
-    if ("$imm:$dst" =~ /\$([0-9]+):%xmm([0-9]+)/) {
+    if (shift =~ /\$([0-9]+),(%\w+),%xmm([0-9]+)/) {
       my @opcode=(0x66);
        $imm=$1;
-       $dst=$2;
-       if ($src =~ /%r([0-9]+)d/)      { $src = $1; }
+       $src=$2;
+       $dst=$3;
+       if ($src =~ /%r([0-9]+)/)       { $src = $1; }
        elsif ($src =~ /%e/)            { $src = $regrm{$src}; }
        rex(\@opcode,$dst,$src);
        push @opcode,0x0f,0x3a,0x22;
        push @opcode,0xc0|(($dst&7)<<3)|($src&7);       # ModR/M
        push @opcode,$imm;
-       printf "\t.byte\t%s\n",join(',',@opcode);
+       @opcode;
     } else {
-       printf "\tpinsrd\t%s\n",join(',',@_);
+       ();
     }
-} if ($gas);
+};
 
 my $pshufb = sub {
-  my ($src,$dst) = @_;
-    if ("$dst:$src" =~ /%xmm([0-9]+):%xmm([0-9]+)/) {
+    if (shift =~ /%xmm([0-9]+),%xmm([0-9]+)/) {
       my @opcode=(0x66);
-       rex(\@opcode,$1,$2);
+       rex(\@opcode,$2,$1);
        push @opcode,0x0f,0x38,0x00;
-       push @opcode,0xc0|($2&7)|(($1&7)<<3);   # ModR/M
-       printf "\t.byte\t%s\n",join(',',@opcode);
+       push @opcode,0xc0|($1&7)|(($2&7)<<3);           # ModR/M
+       @opcode;
+    } else {
+       ();
+    }
+};
+
+my $palignr = sub {
+    if (shift =~ /\$([0-9]+),%xmm([0-9]+),%xmm([0-9]+)/) {
+      my @opcode=(0x66);
+       rex(\@opcode,$3,$2);
+       push @opcode,0x0f,0x3a,0x0f;
+       push @opcode,0xc0|($2&7)|(($3&7)<<3);           # ModR/M
+       push @opcode,$1;
+       @opcode;
+    } else {
+       ();
+    }
+};
+
+my $pclmulqdq = sub {
+    if (shift =~ /\$([x0-9a-f]+),\s*%xmm([0-9]+),\s*%xmm([0-9]+)/) {
+      my @opcode=(0x66);
+       rex(\@opcode,$3,$2);
+       push @opcode,0x0f,0x3a,0x44;
+       push @opcode,0xc0|($2&7)|(($3&7)<<3);           # ModR/M
+       my $c=$1;
+       push @opcode,$c=~/^0/?oct($c):$c;
+       @opcode;
     } else {
-       printf "\tpshufb\t%s\n",join(',',@_);
+       ();
     }
-} if ($gas);
+};
 
 if ($nasm) {
     print <<___;
 default        rel
+%define XMMWORD
 ___
 } elsif ($masm) {
     print <<___;
@@ -706,14 +738,22 @@ while($line=<>) {
 
     undef $label;
     undef $opcode;
-    undef $sz;
     undef @args;
 
     if ($label=label->re(\$line))      { print $label->out(); }
 
     if (directive->re(\$line)) {
        printf "%s",directive->out();
-    } elsif ($opcode=opcode->re(\$line)) { ARGUMENT: while (1) {
+    } elsif ($opcode=opcode->re(\$line)) {
+       my $asm = eval("\$".$opcode->mnemonic());
+       undef @bytes;
+       
+       if ((ref($asm) eq 'CODE') && scalar(@bytes=&$asm($line))) {
+           print $gas?".byte\t":"DB\t",join(',',@bytes),"\n";
+           next;
+       }
+
+       ARGUMENT: while (1) {
        my $arg;
 
        if ($arg=register->re(\$line))  { opcode->size($arg->size()); }
@@ -729,22 +769,21 @@ while($line=<>) {
        $line =~ s/^,\s*//;
        } # ARGUMENT:
 
-       $sz=opcode->size();
-
        if ($#args>=0) {
            my $insn;
+           my $sz=opcode->size();
+
            if ($gas) {
                $insn = $opcode->out($#args>=1?$args[$#args]->size():$sz);
                @args = map($_->out($sz),@args);
-               my $asm = eval("\$$insn");
-               if (ref($asm) eq 'CODE') { &$asm(@args); }
-               else { printf "\t%s\t%s",$insn,join(",",@args); }
+               printf "\t%s\t%s",$insn,join(",",@args);
            } else {
                $insn = $opcode->out();
                foreach (@args) {
                    my $arg = $_->out();
-                   if ($arg =~ /xmm/) { $insn.=$sz; $sz="o"; last; }
-                   if ($arg =~ /mm/)  { $insn.=$sz; $sz="q"; last; }
+                   # $insn.=$sz compensates for movq, pinsrw, ...
+                   if ($arg =~ /^xmm[0-9]+$/) { $insn.=$sz; $sz="x" if(!$sz); last; }
+                   if ($arg =~ /^mm[0-9]+$/)  { $insn.=$sz; $sz="q" if(!$sz); last; }
                }
                @args = reverse(@args);
                undef $sz if ($nasm && $opcode->mnemonic() eq "lea");