perlasm/x86*: add support to SSE>2 and pclmulqdq. x86_64-xlate.pl provides
[openssl.git] / crypto / perlasm / x86asm.pl
index 4f3b5063c448dc1788648e27730cdea03a0c53ad..f09152adb6ec85d25e354bec33514fafb3fe008e 100644 (file)
@@ -17,7 +17,7 @@ $i386=0;
 sub ::AUTOLOAD
 { my $opcode = $AUTOLOAD;
 
-    die "more than 2 arguments passed to $opcode" if ($#_>1);
+    die "more than 4 arguments passed to $opcode" if ($#_>3);
 
     $opcode =~ s/.*:://;
     if    ($opcode =~ /^push/) { $stack+=4; }
@@ -66,8 +66,8 @@ sub ::rotr    { &ror(@_);     }
 sub ::exch     { &xchg(@_);    }
 sub ::halt     { &hlt;         }
 sub ::movz     { &movzx(@_);   }
-sub ::pushf    { &::pushfd;    }
-sub ::popf     { &::popfd;     }
+sub ::pushf    { &pushfd;      }
+sub ::popf     { &popfd;       }
 
 # 3 argument instructions
 sub ::movq
@@ -79,9 +79,50 @@ sub ::movq
     else
     {  &::generic("movq",@_);                  }
 }
-sub ::pshufw   { &::emit("pshufw",@_); }
-sub ::shld     { &::emit("shld",@_);   }
-sub ::shrd     { &::emit("shrd",@_);   }
+
+# SSE>2 instructions
+my %regrm = (  "eax"=>0, "ecx"=>1, "edx"=>2, "ebx"=>3,
+               "esp"=>4, "ebp"=>5, "esi"=>6, "edi"=>7  );
+sub ::pextrd
+{ my($dst,$src,$imm)=@_;
+    if ("$dst:$src" =~ /(e[a-dsd][ixp]):xmm([0-7])/)
+    {  &data_byte(0x66,0x0f,0x3a,0x16,0xc0|($2<<3)|$regrm{$1},$imm);   }
+}
+
+sub ::pinsrd
+{ my($dst,$src,$imm)=@_;
+    if ("$dst:$src" =~ /xmm([0-7]):(e[a-dsd][ixp])/)
+    {  &data_byte(0x66,0x0f,0x3a,0x22,0xc0|($1<<3)|$regrm{$2},$imm);   }
+}
+
+sub ::pshufb
+{ my($dst,$src)=@_;
+    if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+    {  &data_byte(0x66,0x0f,0x38,0x00,0xc0|($1<<3)|$2);        }
+}
+
+# AESNI extenstion
+sub ::aeskeygenassist
+{ my($dst,$src,$imm)=@_;
+    if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+    {  &data_byte(0x66,0x0f,0x3a,0xdf,0xc0|($1<<3)|$2,$imm);   }
+}
+sub ::aescommon
+{ my($opcodelet,$dst,$src)=@_;
+    if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+    {  &data_byte(0x66,0x0f,0x38,$opcodelet,0xc0|($1<<3)|$2);  }
+}
+sub ::aesimc           { ::aescommon(0xdb,@_); }
+sub ::aesenc           { ::aescommon(0xdc,@_); }
+sub ::aesenclast       { ::aescommon(0xdd,@_); }
+sub ::aesdec           { ::aescommon(0xde,@_); }
+sub ::aesdeclast       { ::aescommon(0xdf,@_); }
+
+sub ::pclmulqdq
+{ my($dst,$src,$imm)=@_;
+    if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+    {  &data_byte(0x66,0x0f,0x3a,0x44,0xc0|($1<<3)|$2,$imm);   }
+}
 
 # label management
 $lbdecor="L";          # local label decoration, set by package
@@ -170,7 +211,7 @@ sub ::asm_init
     $filename=$fn;
     $i386=$cpu;
 
-    $elf=$cpp=$coff=$aout=$win32=$netware=$mwerks=0;
+    $elf=$cpp=$coff=$aout=$macosx=$win32=$netware=$mwerks=0;
     if    (($type eq "elf"))
     {  $elf=1;                 require "x86gas.pl";    }
     elsif (($type eq "a\.out"))
@@ -185,6 +226,8 @@ sub ::asm_init
     #{ $netware=1; $mwerks=1;  require "x86nasm.pl";   }
     elsif (($type eq "win32"))
     {  $win32=1;               require "x86masm.pl";   }
+    elsif (($type eq "macosx"))
+    {  $aout=1; $macosx=1;     require "x86gas.pl";    }
     else
     {  print STDERR <<"EOF";
 Pick one target type from
@@ -193,6 +236,7 @@ Pick one target type from
        coff    - GAS/COFF such as Win32 targets
        win32n  - Windows 95/Windows NT NASM format
        nw-nasm - NetWare NASM format
+       macosx  - Mac OS X
 EOF
        exit(1);
     }