]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Versions of Tom's excellent insn-set test programs modified for the
authorJulian Seward <jseward@acm.org>
Mon, 9 May 2005 22:01:37 +0000 (22:01 +0000)
committerJulian Seward <jseward@acm.org>
Mon, 9 May 2005 22:01:37 +0000 (22:01 +0000)
amd64 insn set.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3647

none/tests/amd64/gen_insn_test.pl [new file with mode: 0644]
none/tests/amd64/insn_mmx.def [new file with mode: 0644]

diff --git a/none/tests/amd64/gen_insn_test.pl b/none/tests/amd64/gen_insn_test.pl
new file mode 100644 (file)
index 0000000..7fcfc4e
--- /dev/null
@@ -0,0 +1,984 @@
+#!/usr/bin/perl
+
+use 5.006;
+use strict;
+use warnings;
+
+our %ArgTypes = (
+                 r8 => "reg8_t",
+                 r16 => "reg16_t",
+                 r32 => "reg32_t",
+                 r64 => "reg64_t",
+                 mm => "reg64_t",
+                 xmm => "reg128_t",
+                 m8 => "reg8_t",
+                 m16 => "reg16_t",
+                 m32 => "reg32_t",
+                 m64 => "reg64_t",
+                 m128 => "reg128_t",
+                 eflags => "reg32_t",
+                 st => "reg64_t",
+                 fpucw => "reg16_t",
+                 fpusw => "reg16_t"
+                 );
+
+our %SubTypeFormats = (
+                       sb => "%d",
+                       ub => "%u",
+                       sw => "%d",
+                       uw => "%u",
+                       sd => "%d",
+                       ud => "%u",
+                       sq => "%lld",
+                       uq => "%llu",
+                       ps => "%.16g",
+                       pd => "%.16g"
+                       );
+
+our %SubTypeSuffixes = (
+                        sb => "",
+                        ub => "U",
+                        sw => "",
+                        uw => "",
+                        sd => "",
+                        ud => "",
+                        sq => "LL",
+                        uq => "ULL",
+                        ps => "F",
+                        pd => ""
+                        );
+
+our %RegNums = (
+                al => 0, ax => 0, eax => 0, rax => 0,
+                bl => 1, bx => 1, ebx => 1, rbx => 1,
+                cl => 2, cx => 2, ecx => 2, rcx => 2,
+                dl => 3, dx => 3, edx => 3, rdx => 3,
+                ah => 4,
+                bh => 5,
+                ch => 6,
+                dh => 7,
+                st0 => 0, st1 => 1, st2 => 2, st3 => 3,
+                st4 => 4, st5 => 5, st6 => 6, st7 => 7
+                );
+
+our %RegTypes = (
+                 al => "r8", ah => "r8", ax => "r16", eax => "r32", rax => "r64",
+                 bl => "r8", bh => "r8", bx => "r16", ebx => "r32", rbx => "r64",
+                 cl => "r8", ch => "r8", cx => "r16", ecx => "r32", rcx => "r64",
+                 dl => "r8", dh => "r8", dx => "r16", edx => "r32", rdx => "r64"
+                 );
+
+our @IntRegs = (
+                { r8 => "al", r16 => "ax", r32 => "eax", r64 => "rax" },
+                { r8 => "bl", r16 => "bx", r32 => "ebx", r64 => "rbx" },
+                { r8 => "cl", r16 => "cx", r32 => "ecx", r64 => "rcx" },
+                { r8 => "dl", r16 => "dx", r32 => "edx", r64 => "rdx" },
+                { r8 => "ah" },
+                { r8 => "bh" },
+                { r8 => "ch" },
+                { r8 => "dh" }
+                );
+
+print <<EOF;
+#include <math.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef union {
+  char sb[1];
+  unsigned char ub[1];
+} reg8_t;
+
+typedef union {
+  char sb[2];
+  unsigned char ub[2];
+  short sw[1];
+  unsigned short uw[1];
+} reg16_t;
+
+typedef union {
+  char sb[4];
+  unsigned char ub[4];
+  short sw[2];
+  unsigned short uw[2];
+  int sd[1];
+  unsigned int ud[1];
+  float ps[1];
+} reg32_t;
+
+typedef union {
+  char sb[8];
+  unsigned char ub[8];
+  short sw[4];
+  unsigned short uw[4];
+  int sd[2];
+  unsigned int ud[2];
+  long long int sq[1];
+  unsigned long long int uq[1];
+  float ps[2];
+  double pd[1];
+} reg64_t __attribute__ ((aligned (8)));
+
+typedef union {
+  char sb[16];
+  unsigned char ub[16];
+  short sw[8];
+  unsigned short uw[8];
+  int sd[4];
+  unsigned int ud[4];
+  long long int sq[2];
+  unsigned long long int uq[2];
+  float ps[4];
+  double pd[2];
+} reg128_t __attribute__ ((aligned (16)));
+
+static sigjmp_buf catchpoint;
+
+static void handle_sigill(int signum)
+{
+   siglongjmp(catchpoint, 1);
+}
+
+__attribute__((unused))
+static int eq_float(float f1, float f2)
+{
+   return f1 == f2 || fabsf(f1 - f2) < fabsf(f1) * 1.5 * pow(2,-12);
+}
+
+__attribute__((unused))
+static int eq_double(double d1, double d2)
+{
+   return d1 == d2 || fabs(d1 - d2) < fabs(d1) * 1.5 * pow(2,-12);
+}
+
+EOF
+
+my %tests;
+my @tests;
+
+while (<>)
+{
+    next if /^#/;
+
+    my $insn;
+    my $presets;
+    my $args;
+    my $results;
+
+    if (/^(\S+)\s+(?:(\S+(?:\s+\S+)*)\s+:\s+)?((?:\S+\s+)*?)(?:=>\s+(\S+(?:\s+\S+)*))?$/)
+    {
+        $insn = $1;
+        $presets = $2 || "";
+        $args = $3 || "";
+        $results = $4 || "";
+
+#        print STDERR "insn: $insn\n";
+#        print STDERR "presets: $presets\n";
+#        print STDERR "args: $args\n";
+#        print STDERR "results: $results\n";
+    }
+    else
+    {
+        die "Can't parse test $_";
+    }
+    
+    $tests{$insn}++;
+    
+    my $test = "${insn}_$tests{$insn}";
+    
+    push @tests, $test;
+    
+    print qq|static void $test(void)\n|;
+    print qq|\{\n|;
+
+    my @intregs = @IntRegs;
+    my @mmregs  = map { "mm$_" }  (6,7,0,1,2,3,4,5);
+    my @xmmregs = map { "xmm$_" } (4,5,0,1,2,3,6,7);
+    my @fpregs  = map { "st$_" }  (0 .. 7);
+
+    my @presets;
+    my $presetc = 0;
+    my $eflagsmask;
+    my $eflagsset;
+    my $fpucwmask;
+    my $fpucwset;
+    my $fpuswmask;
+    my $fpuswset;
+
+    foreach my $preset (split(/\s+/, $presets))
+    {
+        if ($preset =~ /^([abcd][lh]|[abcd]x|e[abcd]x|r[abcd]x)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/)
+        {
+            my $name = "preset$presetc";
+            my $type = $RegTypes{$1};
+            my $regnum = $RegNums{$1};
+            my $register = $intregs[$regnum];
+            my $subtype = $2;
+            my @values = split(/,/, $3);
+    
+            die "Register $1 already used" unless defined($register);
+
+            my $preset = {
+                name => $name,
+                type => $type,
+                subtype => $subtype,
+                register => $register
+            };
+
+            delete($intregs[$regnum]);
+
+            push @presets, $preset;
+            
+            print qq|   $ArgTypes{$type} $name = \{ .$subtype = \{|;
+            
+            my $valuec = 0;
+            
+            foreach my $value (@values)
+            {
+                print qq|,| if $valuec > 0;
+                print qq| $value$SubTypeSuffixes{$subtype}|;
+                $valuec++;
+            }
+            
+            print qq| \} \};\n|;
+
+            $presetc++;
+        }
+        elsif ($preset =~ /^st([0-9]+)\.(ps|pd)\[([^\]]+)\]$/)
+        {
+            my $name = "preset$presetc";
+            my $type = "st";
+            my $regnum = $1;
+            my $register = $fpregs[$regnum];
+            my $subtype = $2;
+            my @values = split(/,/, $3);
+
+            die "Register st$1 already used" unless defined($register);
+
+            my $preset = {
+                name => $name,
+                type => $type,
+                subtype => $subtype,
+                register => $register
+            };
+
+            delete($fpregs[$regnum]);
+
+            push @presets, $preset;
+            
+            print qq|   $ArgTypes{$type} $name = \{ .$subtype = \{|;
+            
+            my $valuec = 0;
+            
+            foreach my $value (@values)
+            {
+                print qq|,| if $valuec > 0;
+                print qq| $value$SubTypeSuffixes{$subtype}|;
+                $valuec++;
+            }
+            
+            print qq| \} \};\n|;
+
+            $presetc++;
+        }
+        elsif ($preset =~ /^(eflags)\[([^\]]+)\]$/)
+        {
+            my $type = $1;
+            my @values = split(/,/, $2);
+
+            $values[0] = oct($values[0]) if $values[0] =~ /^0/;
+            $values[1] = oct($values[1]) if $values[1] =~ /^0/;
+
+            $eflagsmask = sprintf "0x%08x", $values[0] ^ 0xffffffff;
+            $eflagsset = sprintf "0x%08x", $values[1];
+        }
+        elsif ($preset =~ /^(fpucw)\[([^\]]+)\]$/)
+        {
+            my $type = $1;
+            my @values = split(/,/, $2);
+
+            $values[0] = oct($values[0]) if $values[0] =~ /^0/;
+            $values[1] = oct($values[1]) if $values[1] =~ /^0/;
+
+            $fpucwmask = sprintf "0x%04x", $values[0] ^ 0xffff;
+            $fpucwset = sprintf "0x%04x", $values[1];
+        }
+        elsif ($preset =~ /^(fpusw)\[([^\]]+)\]$/)
+        {
+            my $type = $1;
+            my @values = split(/,/, $2);
+
+            $values[0] = oct($values[0]) if $values[0] =~ /^0/;
+            $values[1] = oct($values[1]) if $values[1] =~ /^0/;
+
+            $fpuswmask = sprintf "0x%04x", $values[0] ^ 0xffff;
+            $fpuswset = sprintf "0x%04x", $values[1];
+        }
+        else
+        {
+            die "Can't parse preset $preset";
+        }
+    }
+
+    my @args;
+    my $argc = 0;
+    
+    foreach my $arg (split(/\s+/, $args))
+    {
+        my $name = "arg$argc";
+
+        if ($arg =~ /^([abcd]l|[abcd]x|e[abcd]x|r[abcd]x|r8|r16|r32|r64|mm|xmm|m8|m16|m32|m64|m128)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/)
+        {
+            my $type = $RegTypes{$1} || $1;
+            my $regnum = $RegNums{$1};
+            my $register = $intregs[$regnum] if defined($regnum);
+            my $subtype = $2;
+            my @values = split(/,/, $3);
+            
+            die "Register $1 already used" if defined($regnum) && !defined($register);
+
+            my $arg = {
+                name => $name,
+                type => $type,
+                subtype => $subtype
+            };
+
+            if (defined($register))
+            {
+                $arg->{register} = $register;
+                delete($intregs[$regnum]);
+            }
+
+            push @args, $arg;
+            
+            print qq|   $ArgTypes{$type} $name = \{ .$subtype = \{|;
+            
+            my $valuec = 0;
+            
+            foreach my $value (@values)
+            {
+                print qq|,| if $valuec > 0;
+                print qq| $value$SubTypeSuffixes{$subtype}|;
+                $valuec++;
+            }
+
+            print qq| \} \};\n|;
+        }
+        elsif ($arg =~ /^st([0-9]+)\.(ps|pd)\[([^\]]+)\]$/)
+        {
+            my $type = "st";
+            my $regnum = $1;
+            my $register = $fpregs[$regnum] if defined($regnum);
+            my $subtype = $2;
+            my @values = split(/,/, $3);
+            
+            die "Register st$1 already used" if defined($regnum) && !defined($register);
+
+            my $arg = {
+                name => $name,
+                type => $type,
+                subtype => $subtype
+            };
+
+            if (defined($register))
+            {
+                $arg->{register} = $register;
+                delete($fpregs[$regnum]);
+            }
+
+            push @args, $arg;
+            
+            print qq|   $ArgTypes{$type} $name = \{ .$subtype = \{|;
+            
+            my $valuec = 0;
+            
+            foreach my $value (@values)
+            {
+                print qq|,| if $valuec > 0;
+                print qq| $value$SubTypeSuffixes{$subtype}|;
+                $valuec++;
+            }
+
+            print qq| \} \};\n|;
+        }
+        elsif ($arg =~ /^(imm8|imm16|imm32)\[([^\]]+)\]$/)
+        {
+            my $type = $1;
+            my $value = $2;
+            
+            my $arg = {
+                type => $type,
+                value => $value
+            };
+
+            push @args, $arg;
+        }
+        else
+        {
+            die "Can't parse argument $arg";
+        }
+
+        $argc++;
+    }
+    
+    foreach my $arg (@presets, @args)
+    {
+        if ($arg->{type} =~ /^(r8|r16|r32|r64|m8|m16|m32)$/)
+        {
+            while (!exists($arg->{register}) || !defined($arg->{register}))
+            {
+                $arg->{register} = shift @intregs;
+            }
+
+            $arg->{register} = $arg->{register}->{$arg->{type}};
+        }
+        elsif ($arg->{type} =~ /^(mm|m64)$/)
+        {
+            $arg->{register} = shift @mmregs;
+        }
+        elsif ($arg->{type} =~ /^(xmm|m128)$/)
+        {
+            $arg->{register} = shift @xmmregs;
+        }
+        elsif ($arg->{type} =~ /^st$/)
+        {
+            while (!exists($arg->{register}) || !defined($arg->{register}))
+            {
+                $arg->{register} = shift @fpregs;
+            }
+        }
+    }
+
+    my @results;
+    my $resultc = 0;
+    
+    foreach my $result (split(/\s+/, $results))
+    {
+        my $name = "result$resultc";
+    
+        if ($result =~ /^(\d+)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/)
+        {
+            my $index = $1;
+            my $type = $args[$index]->{type};
+            my $subtype = $2;
+            my @values = split(/,/, $3);
+            
+            die "Argument $index not specified" unless exists($args[$index]);
+
+            my $result = {
+                name => $name,
+                type => $type,
+                subtype => $subtype,
+                arg => $args[$index],
+                register => $args[$index]->{register},
+                values => [ @values ]
+            };
+
+            push @results, $result;
+
+            print qq|   $ArgTypes{$type} $name|;
+            print qq| = arg$index| if $type =~ /^m(8|16|32|64|128)$/;
+            print qq|;\n|;
+
+            $args[$index]->{result} = $result;
+        }
+        elsif ($result =~ /^([abcd][lh]|[abcd]x|e[abcd]x|r[abcd]x)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/)
+        {
+            my $register = $1;
+            my $type = $RegTypes{$register};
+            my $subtype = $2;
+            my @values = split(/,/, $3);
+                        
+            my $result = {
+                name => $name,
+                type => $type,
+                subtype => $subtype,
+                register => $register,
+                values => [ @values ]
+            };
+
+            push @results, $result;
+
+            print qq|   $ArgTypes{$type} $name;\n|;
+        }
+        elsif ($result =~ /^(st[0-9]+)\.(ps|pd)\[([^\]]+)\]$/)
+        {
+            my $register = $1;
+            my $type = "st";
+            my $subtype = $2;
+            my @values = split(/,/, $3);
+                        
+            my $result = {
+                name => $name,
+                type => $type,
+                subtype => $subtype,
+                register => $register,
+                values => [ @values ]
+            };
+
+            push @results, $result;
+
+            print qq|   $ArgTypes{$type} $name;\n|;
+        }
+        elsif ($result =~ /^eflags\[([^\]]+)\]$/)
+        {
+            my @values = split(/,/, $1);
+            
+            $values[0] = oct($values[0]) if $values[0] =~ /^0/;
+            $values[1] = oct($values[1]) if $values[1] =~ /^0/;
+            
+            my $result = {
+                name => $name,
+                type => "eflags",
+                subtype => "ud",
+                values => [ map { sprintf "0x%08x", $_ } @values ]
+            };
+
+            push @results, $result;
+            
+            print qq|   $ArgTypes{eflags} $name;\n|;
+
+            if (!defined($eflagsmask) && !defined($eflagsset))
+            {
+                $eflagsmask = sprintf "0x%08x", $values[0] ^ 0xffffffff;
+                $eflagsset = sprintf "0x%08x", $values[0] & ~$values[1];
+            }
+        }
+        elsif ($result =~ /^fpucw\[([^\]]+)\]$/)
+        {
+            my @values = split(/,/, $1);
+            
+            $values[0] = oct($values[0]) if $values[0] =~ /^0/;
+            $values[1] = oct($values[1]) if $values[1] =~ /^0/;
+            
+            my $result = {
+                name => $name,
+                type => "fpucw",
+                subtype => "ud",
+                values => [ map { sprintf "0x%04x", $_ } @values ]
+            };
+
+            push @results, $result;
+            
+            print qq|   $ArgTypes{fpucw} $name;\n|;
+
+            if (!defined($fpucwmask) && !defined($fpucwset))
+            {
+                $fpucwmask = sprintf "0x%04x", $values[0] ^ 0xffff;
+                $fpucwset = sprintf "0x%04x", $values[0] & ~$values[1];
+            }
+        }
+        elsif ($result =~ /^fpusw\[([^\]]+)\]$/)
+        {
+            my @values = split(/,/, $1);
+            
+            $values[0] = oct($values[0]) if $values[0] =~ /^0/;
+            $values[1] = oct($values[1]) if $values[1] =~ /^0/;
+            
+            my $result = {
+                name => $name,
+                type => "fpusw",
+                subtype => "ud",
+                values => [ map { sprintf "0x%04x", $_ } @values ]
+            };
+
+            push @results, $result;
+            
+            print qq|   $ArgTypes{fpusw} $name;\n|;
+
+            if (!defined($fpuswmask) && !defined($fpuswset))
+            {
+                $fpuswmask = sprintf "0x%04x", $values[0] ^ 0xffff;
+                $fpuswset = sprintf "0x%04x", $values[0] & ~$values[1];
+            }
+        }
+        else
+        {
+            die "Can't parse result $result";
+        }
+        
+        $resultc++;
+    }
+    
+    my $argnum = 0;
+
+    foreach my $result (@results)
+    {
+        if ($result->{type} =~ /^(m(8|16|32|64|128)|st|eflags|fpu[cs]w)$/)
+        {
+            $result->{argnum} = $argnum++;
+        }
+    }
+    
+    foreach my $arg (@presets, @args)
+    {
+        if (defined($arg->{name}))
+        {
+            $arg->{argnum} = $argnum++;
+        }
+    }
+    
+    foreach my $result (@results)
+    {
+        if ($result->{type} =~ /^(r(8|16|32|64)|mm|xmm)$/)
+        {
+            $result->{argnum} = $argnum++;
+        }
+    }
+
+    my $stateargnum = $argnum++;
+
+    print qq|   char state\[108\];\n|;
+    print qq|\n|;
+    print qq|   if (sigsetjmp(catchpoint, 1) == 0)\n|;
+    print qq|   \{\n|;
+    print qq|      asm\(\n|;
+#    print qq|         \"fsave %$stateargnum\\n\"\n|;
+    
+    my @fpargs;
+
+    foreach my $arg (@presets, @args)
+    {
+        if ($arg->{type} eq "r8")
+        {
+            print qq|         \"movb %$arg->{argnum}, %%$arg->{register}\\n\"\n|;
+        }
+        elsif ($arg->{type} eq "r16")
+        {
+            print qq|         \"movw %$arg->{argnum}, %%$arg->{register}\\n\"\n|;
+        }
+        elsif ($arg->{type} eq "r32")
+        {
+            print qq|         \"movl %$arg->{argnum}, %%$arg->{register}\\n\"\n|;
+        }
+        elsif ($arg->{type} eq "r64")
+        {
+            print qq|         \"movq %$arg->{argnum}, %%$arg->{register}\\n\"\n|;
+        }
+        elsif ($arg->{type} eq "mm")
+        {
+            print qq|         \"movq %$arg->{argnum}, %%$arg->{register}\\n\"\n|;
+        }
+        elsif ($arg->{type} eq "xmm")
+        {
+            print qq|         \"movlps 0%$arg->{argnum}, %%$arg->{register}\\n\"\n|;
+            print qq|         \"movhps 8%$arg->{argnum}, %%$arg->{register}\\n\"\n|;
+        }
+        elsif ($arg->{type} eq "st")
+        {
+            $fpargs[$RegNums{$arg->{register}}] = $arg;
+        }
+    }
+    
+    foreach my $arg (reverse @fpargs)
+    {
+        if (defined($arg))
+        {
+            if ($arg->{subtype} eq "ps")
+            {
+                print qq|         \"flds %$arg->{argnum}\\n\"\n|;
+            }
+            elsif ($arg->{subtype} eq "pd")
+            {
+                print qq|         \"fldl %$arg->{argnum}\\n\"\n|;
+            }
+        }
+        else
+        {
+            print qq|         \"fldz\\n\"\n|;
+        }
+    }
+
+    if (defined($eflagsmask) || defined($eflagsset))
+    {
+        print qq|         \"pushfl\\n\"\n|;
+        print qq|         \"andl \$$eflagsmask, (%%esp)\\n\"\n| if defined($eflagsmask);
+        print qq|         \"orl \$$eflagsset, (%%esp)\\n\"\n| if defined($eflagsset);
+        print qq|         \"popfl\\n\"\n|;
+    }
+
+    if (defined($fpucwmask) || defined($fpucwset))
+    {
+        print qq|         \"subl \$2, %%esp\\n\"\n|;
+        print qq|         \"fstcw (%%esp)\\n\"\n|;
+        print qq|         \"andw \$$fpucwmask, (%%esp)\\n\"\n| if defined($fpucwmask);
+        print qq|         \"orw \$$fpucwset, (%%esp)\\n\"\n| if defined($fpucwset);
+        print qq|         \"fldcw (%%esp)\\n\"\n|;
+        print qq|         \"addl \$2, %%esp\\n\"\n|;
+    }
+
+    print qq|         \"$insn|;
+    
+    my $prefix = " ";
+    
+    foreach my $arg (@args)
+    {
+        next if $arg->{type} eq "eflags";
+
+        if ($arg->{type} =~ /^(r8|r16|r32|r64|mm|xmm)$/)
+        {
+            print qq|$prefix%%$arg->{register}|;
+        }
+        elsif ($arg->{type} =~ /^st$/)
+        {
+            my $register = $arg->{register};
+
+            $register =~ s/st(\d+)/st\($1\)/;
+
+            print qq|$prefix%%$register|;
+        }
+        elsif ($arg->{type} =~ /^(m(8|16|32|64|128))$/)
+        {
+            if (exists($arg->{result}))
+            {
+                print qq|$prefix%$arg->{result}->{argnum}|;
+            }
+            else
+            {
+                print qq|$prefix%$arg->{argnum}|;
+            }
+        }
+        elsif ($arg->{type} =~ /^imm(8|16|32)$/)
+        {
+            print qq|$prefix\$$arg->{value}|;
+        }
+
+        $prefix = ", ";
+    }
+
+    print qq|\\n\"\n|;
+
+    my @fpresults;
+
+    foreach my $result (@results)
+    {
+        if ($result->{type} eq "r8")
+        {
+            print qq|         \"movb %%$result->{register}, %$result->{argnum}\\n\"\n|;
+        }
+        elsif ($result->{type} eq "r16")
+        {
+            print qq|         \"movw %%$result->{register}, %$result->{argnum}\\n\"\n|;
+        }
+        elsif ($result->{type} eq "r32")
+        {
+            print qq|         \"movl %%$result->{register}, %$result->{argnum}\\n\"\n|;
+        }
+        elsif ($result->{type} eq "r64")
+        {
+            print qq|         \"movq %%$result->{register}, %$result->{argnum}\\n\"\n|;
+        }
+        elsif ($result->{type} eq "mm")
+        {
+            print qq|         \"movq %%$result->{register}, %$result->{argnum}\\n\"\n|;
+        }
+        elsif ($result->{type} eq "xmm")
+        {
+            print qq|         \"movlps %%$result->{register}, 0%$result->{argnum}\\n\"\n|;
+            print qq|         \"movhps %%$result->{register}, 8%$result->{argnum}\\n\"\n|;
+        }
+        elsif ($result->{type} eq "st")
+        {
+            $fpresults[$RegNums{$result->{register}}] = $result;
+        }
+        elsif ($result->{type} eq "eflags")
+        {
+            print qq|         \"pushfl\\n\"\n|;
+            print qq|         \"popl %$result->{argnum}\\n\"\n|;
+        }
+        elsif ($result->{type} eq "fpucw")
+        {
+            print qq|         \"fstcw %$result->{argnum}\\n\"\n|;
+        }
+        elsif ($result->{type} eq "fpusw")
+        {
+            print qq|         \"fstsw %$result->{argnum}\\n\"\n|;
+        }
+    }
+    
+    foreach my $result (@fpresults)
+    {
+        if (defined($result))
+        {
+            if ($result->{subtype} eq "ps")
+            {
+                print qq|         \"fstps %$result->{argnum}\\n\"\n|;
+            }
+            elsif ($result->{subtype} eq "pd")
+            {
+                print qq|         \"fstpl %$result->{argnum}\\n\"\n|;
+            }
+        }
+        else
+        {
+            print qq|         \"fincstp\\n\"\n|;
+        }
+    }
+
+#    print qq|         \"frstor %$stateargnum\\n\"\n|;
+
+    print qq|         :|;
+
+    $prefix = " ";
+
+    foreach my $result (@results)
+    {
+        if ($result->{type} =~ /^(m(8|16|32|64|128)|st|eflags|fpu[cs]w)$/)
+        {
+            print qq|$prefix\"=m\" \($result->{name}\)|;
+            $prefix = ", ";
+        }
+    }
+
+    print qq|\n|;
+    
+    $prefix = "         : ";
+    
+    foreach my $arg (@presets, @args)
+    {
+        if (defined($arg->{name}))
+        {
+            print qq|$prefix\"m\" \($arg->{name}\)|;
+            $prefix = ", ";
+        }
+    }
+    
+    foreach my $result (@results)
+    {
+        if ($result->{type} =~ /^(r(8|16|32|64)|mm|xmm)$/)
+        {
+            print qq|$prefix\"m\" \($result->{name}\)|;
+            $prefix = ", ";
+        }
+    }
+
+    print qq|$prefix\"m\" \(state[0]\)\n|;
+
+    $prefix = "         : ";
+
+    foreach my $arg (@presets, @args)
+    {
+        if ($arg->{register} && $arg->{type} ne "st")
+        {
+            print qq|$prefix\"$arg->{register}\"|;
+            $prefix = ", ";
+        }
+    }
+
+    print qq|\n|;
+    
+    print qq|      \);\n|;                          
+    print qq|\n|;
+    
+    if (@results)
+    {
+        print qq|      if \(|;
+        
+        $prefix = "";
+        
+        foreach my $result (@results)
+        {
+            my $type = $result->{type};
+            my $subtype = $result->{subtype};
+            my $suffix = $SubTypeSuffixes{$subtype};
+            my @values = @{$result->{values}};
+            
+            if ($type eq "eflags")
+            {
+                print qq|${prefix}\($result->{name}.ud[0] & $values[0]UL\) == $values[1]UL|;
+            }
+            elsif ($type =~ /^fpu[cs]w$/)
+            {
+                print qq|${prefix}\($result->{name}.uw[0] & $values[0]\) == $values[1]|;
+            }
+            else
+            {
+                foreach my $value (0 .. $#values)
+                {
+                    if ($subtype eq "ps")
+                    {
+                        print qq|${prefix}eq_float($result->{name}.$subtype\[$value\], $values[$value]$suffix)|;
+                    }
+                    elsif ($subtype eq "pd")
+                    {
+                        print qq|${prefix}eq_double($result->{name}.$subtype\[$value\], $values[$value]$suffix)|;
+                    }
+                    else
+                    {
+                        print qq|${prefix}$result->{name}.$subtype\[$value\] == $values[$value]$suffix|;
+                    }
+                    
+                    $prefix = " && ";
+                }
+            }
+            
+            $prefix = " &&\n          ";
+        }
+        
+        print qq| \)\n|;
+        print qq|      \{\n|;
+        print qq|         printf("$test ... ok\\n");\n|;
+        print qq|      \}\n|;
+        print qq|      else\n|;
+        print qq|      \{\n|;
+        print qq|         printf("$test ... not ok\\n");\n|;
+        
+        foreach my $result (@results)
+        {
+            my $type = $result->{type};
+            my $subtype = $result->{subtype};
+            my $suffix = $SubTypeSuffixes{$subtype};
+            my @values = @{$result->{values}};
+            
+            if ($type eq "eflags")
+            {
+                print qq|         printf("  eflags & 0x%lx = 0x%lx (expected 0x%lx)\\n", $values[0]UL, $result->{name}.ud\[0\] & $values[0]UL, $values[1]UL);\n|;
+            }
+            elsif ($type =~ /^fpu[cs]w$/)
+            {
+                print qq|         printf("  $type & 0x%x = 0x%x (expected 0x%x)\\n", $values[0], $result->{name}.uw\[0\] & $values[0], $values[1]);\n|;
+            }
+            else
+            {
+                foreach my $value (0 .. $#values)
+                {
+                    print qq|         printf("  $result->{name}.$subtype\[$value\] = $SubTypeFormats{$subtype} (expected $SubTypeFormats{$subtype})\\n", $result->{name}.$subtype\[$value\], $values[$value]$suffix);\n|;
+                }
+            }
+        }
+        
+        print qq|      \}\n|;
+    }
+    else
+    {
+        print qq|      printf("$test ... ok\\n");\n|;
+    }
+
+    print qq|   \}\n|;
+    print qq|   else\n|;
+    print qq|   \{\n|;
+    print qq|      printf("$test ... failed\\n");\n|;
+    print qq|   \}\n|;
+    print qq|\n|;
+    print qq|   return;\n|;
+    print qq|\}\n|;
+    print qq|\n|;
+}
+
+print qq|int main(int argc, char **argv)\n|;
+print qq|\{\n|;
+print qq|   signal(SIGILL, handle_sigill);\n|;
+print qq|\n|;
+
+foreach my $test (@tests)
+{
+    print qq|   $test();\n|;
+}
+
+print qq|\n|;
+print qq|   exit(0);\n|;
+print qq|\}\n|;
+
+exit 0;
diff --git a/none/tests/amd64/insn_mmx.def b/none/tests/amd64/insn_mmx.def
new file mode 100644 (file)
index 0000000..f7cc057
--- /dev/null
@@ -0,0 +1,123 @@
+#
+# %mm <-> ireg64
+#
+movd mm.sd[1234,5678] r64.sd[1111,2222] => 1.sd[1234,5678]
+movd r64.sd[1234,5678] mm.sd[1111,2222] => 1.sd[1234,5678]
+#
+# %mm <-> ireg32
+#
+movd r32.sd[1234] mm.sd[1111,2222] => 1.sd[1234,0]
+movd mm.sd[1234,2222] r32.sd[1111] => 1.sd[1234]
+#
+# %mm <-> mem32
+#
+movd m32.sd[1234] mm.sd[1111,2222] => 1.sd[1234,0]
+movd mm.sd[1234,2222] m32.sd[1111] => 1.sd[1234]
+#
+# %mm <-> mem64
+#
+movq m64.uq[0x012345678abcdef] mm.uq[0x1212121234343434] => 1.uq[0x012345678abcdef]
+movq mm.uq[0x012345678abcdef] m64.uq[0x1212121234343434] => 1.uq[0x012345678abcdef]
+#
+# %mm -> %mm
+#
+movq mm.uq[0x012345678abcdef] mm.uq[0x1212121234343434] => 1.uq[0x012345678abcdef]
+#
+#
+#
+packssdw mm.sd[12345,123456] mm.sd[-12345,-123456] => 1.sw[-12345,-32768,12345,32767]
+packssdw m64.sd[12345,123456] mm.sd[-12345,-123456] => 1.sw[-12345,-32768,12345,32767]
+packsswb mm.sw[123,-123,1234,-1234] mm.sw[21,-21,321,-321] => 1.sb[21,-21,127,-128,123,-123,127,-128]
+packsswb m64.sw[123,-123,1234,-1234] mm.sw[21,-21,321,-321] => 1.sb[21,-21,127,-128,123,-123,127,-128]
+packuswb mm.sw[123,-123,1234,-1234] mm.sw[21,-21,321,-321] => 1.ub[21,0,255,0,123,0,255,0]
+packuswb m64.sw[123,-123,1234,-1234] mm.sw[21,-21,321,-321] => 1.ub[21,0,255,0,123,0,255,0]
+paddb mm.sb[12,34,56,78,21,43,65,87] mm.sb[8,7,6,5,4,3,2,1] => 1.sb[20,41,62,83,25,46,67,88]
+paddb m64.sb[12,34,56,78,21,43,65,87] mm.sb[8,7,6,5,4,3,2,1] => 1.sb[20,41,62,83,25,46,67,88]
+paddd mm.sd[12345678,87654321] mm.sd[8765,4321] => 1.sd[12354443,87658642]
+paddd m64.sd[12345678,87654321] mm.sd[8765,4321] => 1.sd[12354443,87658642]
+paddsb mm.sb[25,-25,50,-50,100,-100,125,-125] mm.sb[40,-40,30,-30,20,-20,10,-10] => 1.sb[65,-65,80,-80,120,-120,127,-128]
+paddsb m64.sb[25,-25,50,-50,100,-100,125,-125] mm.sb[40,-40,30,-30,20,-20,10,-10] => 1.sb[65,-65,80,-80,120,-120,127,-128]
+paddsw mm.sw[12345,-12345,32145,-32145] mm.sw[32145,-32145,-12345,12345] => 1.sw[32767,-32768,19800,-19800]
+paddsw m64.sw[12345,-12345,32145,-32145] mm.sw[32145,-32145,-12345,12345] => 1.sw[32767,-32768,19800,-19800]
+paddusb mm.ub[25,50,75,100,125,150,175,200] mm.ub[10,20,30,40,50,60,70,80] => 1.ub[35,70,105,140,175,210,245,255]
+paddusb m64.ub[25,50,75,100,125,150,175,200] mm.ub[10,20,30,40,50,60,70,80] => 1.ub[35,70,105,140,175,210,245,255]
+paddusw mm.uw[22222,33333,44444,55555] mm.uw[6666,7777,8888,9999] => 1.uw[28888,41110,53332,65535]
+paddusw m64.uw[22222,33333,44444,55555] mm.uw[6666,7777,8888,9999] => 1.uw[28888,41110,53332,65535]
+paddw mm.sw[1234,5678,4321,8765] mm.sw[87,65,43,21] => 1.sw[1321,5743,4364,8786]
+paddw m64.sw[1234,5678,4321,8765] mm.sw[87,65,43,21] => 1.sw[1321,5743,4364,8786]
+pand mm.uq[0xfdb97531eca86420] mm.uq[0x0123456789abcdef] => 1.uq[0x0121452188a84420]
+pand m64.uq[0xfdb97531eca86420] mm.uq[0x0123456789abcdef] => 1.uq[0x0121452188a84420]
+pandn mm.uq[0xfdb97531eca86420] mm.uq[0x0123456789abcdef] => 1.uq[0xfc98301064002000]
+pandn m64.uq[0xfdb97531eca86420] mm.uq[0x0123456789abcdef] => 1.uq[0xfc98301064002000]
+pcmpeqb mm.ub[11,22,33,44,55,66,77,88] mm.ub[11,11,33,33,55,55,77,77] => 1.ub[0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00]
+pcmpeqb m64.ub[11,22,33,44,55,66,77,88] mm.ub[11,11,33,33,55,55,77,77] => 1.ub[0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00]
+pcmpeqd mm.ud[11223344,55667788] mm.ud[11223344,11223344] => 1.ud[0xffffffff,0x00000000]
+pcmpeqd m64.ud[11223344,55667788] mm.ud[11223344,11223344] => 1.ud[0xffffffff,0x00000000]
+pcmpeqw mm.uw[1122,3344,5566,7788] mm.uw[1122,1122,5566,5566] => 1.uw[0xffff,0x0000,0xffff,0x0000]
+pcmpeqw m64.uw[1122,3344,5566,7788] mm.uw[1122,1122,5566,5566] => 1.uw[0xffff,0x0000,0xffff,0x0000]
+pcmpgtb mm.sb[-77,-55,-33,-11,11,33,55,77] mm.sb[77,55,33,11,-11,-33,-55,-77] => 1.ub[0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00]
+pcmpgtb m64.sb[-77,-55,-33,-11,11,33,55,77] mm.sb[77,55,33,11,-11,-33,-55,-77] => 1.ub[0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00]
+pcmpgtd mm.sd[-11111111,11111111] mm.sd[11111111,-11111111] => 1.ud[0xffffffff,0x00000000]
+pcmpgtd m64.sd[-11111111,11111111] mm.sd[11111111,-11111111] => 1.ud[0xffffffff,0x00000000]
+pcmpgtw mm.sw[-3333,-1111,1111,3333] mm.sw[3333,1111,-1111,-3333] => 1.uw[0xffff,0xffff,0x0000,0x0000]
+pcmpgtw m64.sw[-3333,-1111,1111,3333] mm.sw[3333,1111,-1111,-3333] => 1.uw[0xffff,0xffff,0x0000,0x0000]
+pmaddwd mm.sw[1234,5678,-4321,-8765] mm.sw[1111,-2222,3333,-4444] => 1.sd[-11245542,24549767]
+pmaddwd m64.sw[1234,5678,-4321,-8765] mm.sw[1111,-2222,3333,-4444] => 1.sd[-11245542,24549767]
+pmulhw mm.sw[1111,2222,-1111,-2222] mm.sw[3333,-4444,3333,-4444] => 1.uw[0x0038,0xff69,0xffc7,0x0096]
+pmulhw m64.sw[1111,2222,-1111,-2222] mm.sw[3333,-4444,3333,-4444] => 1.uw[0x0038,0xff69,0xffc7,0x0096]
+pmullw mm.sw[1111,2222,-1111,-2222] mm.sw[3333,-4444,3333,-4444] => 1.uw[0x80b3,0x5378,0x7f4d,0xac88]
+pmullw m64.sw[1111,2222,-1111,-2222] mm.sw[3333,-4444,3333,-4444] => 1.uw[0x80b3,0x5378,0x7f4d,0xac88]
+por mm.uq[0xfdb97531eca86420] mm.uq[0x0123456789abcdef] => 1.uq[0xfdbb7577edabedef]
+por m64.uq[0xfdb97531eca86420] mm.uq[0x0123456789abcdef] => 1.uq[0xfdbb7577edabedef]
+pslld imm8[4] mm.ud[0x01234567,0x89abcdef] => 1.ud[0x12345670,0x9abcdef0]
+pslld mm.uq[4] mm.ud[0x01234567,0x89abcdef] => 1.ud[0x12345670,0x9abcdef0]
+pslld m64.uq[4] mm.ud[0x01234567,0x89abcdef] => 1.ud[0x12345670,0x9abcdef0]
+psllq imm8[4] mm.uq[0x0123456789abcdef] => 1.uq[0x123456789abcdef0]
+psllq mm.uq[4] mm.uq[0x0123456789abcdef] => 1.uq[0x123456789abcdef0]
+psllq m64.uq[4] mm.uq[0x0123456789abcdef] => 1.uq[0x123456789abcdef0]
+psllw imm8[4] mm.uw[0x0123,0x4567,0x89ab,0xcdef] => 1.uw[0x1230,0x5670,0x9ab0,0xdef0]
+psllw mm.uq[4] mm.uw[0x0123,0x4567,0x89ab,0xcdef] => 1.uw[0x1230,0x5670,0x9ab0,0xdef0]
+psllw m64.uq[4] mm.uw[0x0123,0x4567,0x89ab,0xcdef] => 1.uw[0x1230,0x5670,0x9ab0,0xdef0]
+psrad imm8[4] mm.ud[0x01234567,0x89abcdef] => 1.ud[0x00123456,0xf89abcde]
+psrad mm.uq[4] mm.ud[0x01234567,0x89abcdef] => 1.ud[0x00123456,0xf89abcde]
+psrad m64.uq[4] mm.ud[0x01234567,0x89abcdef] => 1.ud[0x00123456,0xf89abcde]
+psraw imm8[4] mm.uw[0x0123,0x4567,0x89ab,0xcdef] => 1.uw[0x0012,0x0456,0xf89a,0xfcde]
+psraw mm.uq[4] mm.uw[0x0123,0x4567,0x89ab,0xcdef] => 1.uw[0x0012,0x0456,0xf89a,0xfcde]
+psraw m64.uq[4] mm.uw[0x0123,0x4567,0x89ab,0xcdef] => 1.uw[0x0012,0x0456,0xf89a,0xfcde]
+psrld imm8[4] mm.ud[0x01234567,0x89abcdef] => 1.ud[0x00123456,0x089abcde]
+psrld mm.uq[4] mm.ud[0x01234567,0x89abcdef] => 1.ud[0x00123456,0x089abcde]
+psrld m64.uq[4] mm.ud[0x01234567,0x89abcdef] => 1.ud[0x00123456,0x089abcde]
+psrlq imm8[4] mm.uq[0x0123456789abcdef] => 1.uq[0x00123456789abcde]
+psrlq mm.uq[4] mm.uq[0x0123456789abcdef] => 1.uq[0x00123456789abcde]
+psrlq m64.uq[4] mm.uq[0x0123456789abcdef] => 1.uq[0x00123456789abcde]
+psrlw imm8[4] mm.uw[0x0123,0x4567,0x89ab,0xcdef] => 1.uw[0x0012,0x0456,0x089a,0x0cde]
+psrlw mm.uq[4] mm.uw[0x0123,0x4567,0x89ab,0xcdef] => 1.uw[0x0012,0x0456,0x089a,0x0cde]
+psrlw m64.uq[4] mm.uw[0x0123,0x4567,0x89ab,0xcdef] => 1.uw[0x0012,0x0456,0x089a,0x0cde]
+psubb mm.sb[8,7,6,5,4,3,2,1] mm.sb[12,34,56,78,21,43,65,87] => 1.sb[4,27,50,73,17,40,63,86]
+psubb m64.sb[8,7,6,5,4,3,2,1] mm.sb[12,34,56,78,21,43,65,87] => 1.sb[4,27,50,73,17,40,63,86]
+psubd mm.sd[8765,4321] mm.sd[12345678,87654321] => 1.sd[12336913,87650000]
+psubd m64.sd[8765,4321] mm.sd[12345678,87654321] => 1.sd[12336913,87650000]
+psubsb mm.sb[-50,50,-40,40,-30,30,-20,20] mm.sb[25,-25,50,-50,100,-100,125,-125] => 1.sb[75,-75,90,-90,127,-128,127,-128]
+psubsb m64.sb[-50,50,-40,40,-30,30,-20,20] mm.sb[25,-25,50,-50,100,-100,125,-125] => 1.sb[75,-75,90,-90,127,-128,127,-128]
+psubsw mm.sw[-32145,32145,12345,-12345] mm.sw[12345,-12345,32145,-32145] => 1.sw[32767,-32768,19800,-19800]
+psubsw m64.sw[-32145,32145,12345,-12345] mm.sw[12345,-12345,32145,-32145] => 1.sw[32767,-32768,19800,-19800]
+psubusb mm.ub[11,22,33,44,55,66,77,88] mm.ub[88,77,66,55,44,33,22,11] => 1.ub[77,55,33,11,0,0,0,0]
+psubusb m64.ub[11,22,33,44,55,66,77,88] mm.ub[88,77,66,55,44,33,22,11] => 1.ub[77,55,33,11,0,0,0,0]
+psubusw mm.uw[1122,3344,5566,7788] mm.uw[8877,6655,4433,2211] => 1.uw[7755,3311,0,0]
+psubusw m64.uw[1122,3344,5566,7788] mm.uw[8877,6655,4433,2211] => 1.uw[7755,3311,0,0]
+psubw mm.sw[87,65,43,21] mm.sw[1234,5678,4321,8765] => 1.sw[1147,5613,4278,8744]
+psubw m64.sw[87,65,43,21] mm.sw[1234,5678,4321,8765] => 1.sw[1147,5613,4278,8744]
+punpckhbw mm.ub[12,34,56,78,21,43,65,87] mm.ub[11,22,33,44,55,66,77,88] => 1.ub[55,21,66,43,77,65,88,87]
+punpckhbw m64.ub[12,34,56,78,21,43,65,87] mm.ub[11,22,33,44,55,66,77,88] => 1.ub[55,21,66,43,77,65,88,87]
+punpckhdq mm.ud[12345678,21436587] mm.ud[11223344,55667788] => 1.ud[55667788,21436587]
+punpckhdq m64.ud[12345678,21436587] mm.ud[11223344,55667788] => 1.ud[55667788,21436587]
+punpckhwd mm.uw[1234,5678,2143,6587] mm.uw[1122,3344,5566,7788] => 1.uw[5566,2143,7788,6587]
+punpckhwd m64.uw[1234,5678,2143,6587] mm.uw[1122,3344,5566,7788] => 1.uw[5566,2143,7788,6587]
+punpcklbw mm.ub[12,34,56,78,21,43,65,87] mm.ub[11,22,33,44,55,66,77,88] => 1.ub[11,12,22,34,33,56,44,78]
+punpcklbw m64.ub[12,34,56,78,21,43,65,87] mm.ub[11,22,33,44,55,66,77,88] => 1.ub[11,12,22,34,33,56,44,78]
+punpckldq mm.ud[12345678,21436587] mm.ud[11223344,55667788] => 1.ud[11223344,12345678]
+punpckldq m64.ud[12345678,21436587] mm.ud[11223344,55667788] => 1.ud[11223344,12345678]
+punpcklwd mm.uw[1234,5678,2143,6587] mm.uw[1122,3344,5566,7788] => 1.uw[1122,1234,3344,5678]
+punpcklwd m64.uw[1234,5678,2143,6587] mm.uw[1122,3344,5566,7788] => 1.uw[1122,1234,3344,5678]
+pxor mm.uq[0xfdb97531eca86420] mm.uq[0x0123456789abcdef] => 1.uq[0xfc9a30566503a9cf]
+pxor m64.uq[0xfdb97531eca86420] mm.uq[0x0123456789abcdef] => 1.uq[0xfc9a30566503a9cf]