From: Julian Seward Date: Mon, 9 May 2005 22:01:37 +0000 (+0000) Subject: Versions of Tom's excellent insn-set test programs modified for the X-Git-Tag: svn/VALGRIND_3_0_0~671 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f39c29a1a819ed49e5901b0dbd121f71508d217d;p=thirdparty%2Fvalgrind.git Versions of Tom's excellent insn-set test programs modified for the amd64 insn set. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3647 --- diff --git a/none/tests/amd64/gen_insn_test.pl b/none/tests/amd64/gen_insn_test.pl new file mode 100644 index 0000000000..7fcfc4ea9c --- /dev/null +++ b/none/tests/amd64/gen_insn_test.pl @@ -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 < +#include +#include +#include +#include + +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 index 0000000000..f7cc057f8d --- /dev/null +++ b/none/tests/amd64/insn_mmx.def @@ -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]