Home | History | Annotate | Download | only in x86
      1 #!/usr/bin/perl
      2 
      3 use 5.006;
      4 use strict;
      5 use warnings;
      6 
      7 our %ArgTypes = (
      8                  r8 => "reg8_t",
      9                  r16 => "reg16_t",
     10                  r32 => "reg32_t",
     11                  mm => "reg64_t",
     12                  xmm => "reg128_t",
     13                  m8 => "reg8_t",
     14                  m16 => "reg16_t",
     15                  m32 => "reg32_t",
     16                  m64 => "reg64_t",
     17                  m128 => "reg128_t",
     18                  eflags => "reg32_t",
     19                  st => "reg64_t",
     20                  fpucw => "reg16_t",
     21                  fpusw => "reg16_t"
     22                  );
     23 
     24 our %SubTypeFormats = (
     25                        sb => "%d",
     26                        ub => "%u",
     27                        sw => "%d",
     28                        uw => "%u",
     29                        sd => "%ld",
     30                        ud => "%lu",
     31                        sq => "%lld",
     32                        uq => "%llu",
     33                        ps => "%.16g",
     34                        pd => "%.16g"
     35                        );
     36 
     37 our %SubTypeSuffixes = (
     38                         sb => "",
     39                         ub => "U",
     40                         sw => "",
     41                         uw => "",
     42                         sd => "L",
     43                         ud => "UL",
     44                         sq => "LL",
     45                         uq => "ULL",
     46                         ps => "F",
     47                         pd => ""
     48                         );
     49 
     50 our %RegNums = (
     51                 al => 0, ax => 0, eax => 0,
     52                 bl => 1, bx => 1, ebx => 1,
     53                 cl => 2, cx => 2, ecx => 2,
     54                 dl => 3, dx => 3, edx => 3,
     55                 ah => 4,
     56                 bh => 5,
     57                 ch => 6,
     58                 dh => 7,
     59                 st0 => 0, st1 => 1, st2 => 2, st3 => 3,
     60                 st4 => 4, st5 => 5, st6 => 6, st7 => 7
     61                 );
     62 
     63 our %RegTypes = (
     64                  al => "r8", ah => "r8", ax => "r16", eax => "r32",
     65                  bl => "r8", bh => "r8", bx => "r16", ebx => "r32",
     66                  cl => "r8", ch => "r8", cx => "r16", ecx => "r32",
     67                  dl => "r8", dh => "r8", dx => "r16", edx => "r32"
     68                  );
     69 
     70 our @IntRegs = (
     71                 { r8 => "al", r16 => "ax", r32 => "eax" },
     72                 { r8 => "bl", r16 => "bx", r32 => "ebx" },
     73                 { r8 => "cl", r16 => "cx", r32 => "ecx" },
     74                 { r8 => "dl", r16 => "dx", r32 => "edx" },
     75                 { r8 => "ah" },
     76                 { r8 => "bh" },
     77                 { r8 => "ch" },
     78                 { r8 => "dh" }
     79                 );
     80 
     81 print <<EOF;
     82 #include <math.h>
     83 #include <setjmp.h>
     84 #include <signal.h>
     85 #include <stdio.h>
     86 #include <stdlib.h>
     87 
     88 typedef union {
     89   char sb[1];
     90   unsigned char ub[1];
     91 } reg8_t;
     92 
     93 typedef union {
     94   char sb[2];
     95   unsigned char ub[2];
     96   short sw[1];
     97   unsigned short uw[1];
     98 } reg16_t;
     99 
    100 typedef union {
    101   char sb[4];
    102   unsigned char ub[4];
    103   short sw[2];
    104   unsigned short uw[2];
    105   long int sd[1];
    106   unsigned long int ud[1];
    107   float ps[1];
    108 } reg32_t;
    109 
    110 typedef union {
    111   char sb[8];
    112   unsigned char ub[8];
    113   short sw[4];
    114   unsigned short uw[4];
    115   long int sd[2];
    116   unsigned long int ud[2];
    117   long long int sq[1];
    118   unsigned long long int uq[1];
    119   float ps[2];
    120   double pd[1];
    121 } reg64_t __attribute__ ((aligned (8)));
    122 
    123 typedef union {
    124   char sb[16];
    125   unsigned char ub[16];
    126   short sw[8];
    127   unsigned short uw[8];
    128   long int sd[4];
    129   unsigned long int ud[4];
    130   long long int sq[2];
    131   unsigned long long int uq[2];
    132   float ps[4];
    133   double pd[2];
    134 } reg128_t __attribute__ ((aligned (16)));
    135 
    136 static sigjmp_buf catchpoint;
    137 
    138 static void handle_sigill(int signum)
    139 {
    140    siglongjmp(catchpoint, 1);
    141 }
    142 
    143 __attribute__((unused))
    144 static int eq_float(float f1, float f2)
    145 {
    146    return f1 == f2 || fabsf(f1 - f2) < fabsf(f1) * 1.5 * pow(2,-12);
    147 }
    148 
    149 __attribute__((unused))
    150 static int eq_double(double d1, double d2)
    151 {
    152    return d1 == d2 || fabs(d1 - d2) < fabs(d1) * 1.5 * pow(2,-12);
    153 }
    154 
    155 EOF
    156 
    157 my %tests;
    158 my @tests;
    159 
    160 while (<>)
    161 {
    162     next if /^#/;
    163 
    164     my $insn;
    165     my $presets;
    166     my $args;
    167     my $results;
    168 
    169     if (/^(\S+)\s+(?:(\S+(?:\s+\S+)*)\s+:\s+)?((?:\S+\s+)*?)(?:=>\s+(\S+(?:\s+\S+)*))?$/)
    170     {
    171         $insn = $1;
    172         $presets = $2 || "";
    173         $args = $3 || "";
    174         $results = $4 || "";
    175 
    176 #        print STDERR "insn: $insn\n";
    177 #        print STDERR "presets: $presets\n";
    178 #        print STDERR "args: $args\n";
    179 #        print STDERR "results: $results\n";
    180     }
    181     else
    182     {
    183         die "Can't parse test $_";
    184     }
    185     
    186     $tests{$insn}++;
    187     
    188     my $test = "${insn}_$tests{$insn}";
    189     
    190     push @tests, $test;
    191     
    192     print qq|static void $test(void)\n|;
    193     print qq|\{\n|;
    194 
    195     my @intregs = @IntRegs;
    196     my @mmregs  = map { "mm$_" }  (6,7,0,1,2,3,4,5);
    197     my @xmmregs = map { "xmm$_" } (4,5,0,1,2,3,6,7);
    198     my @fpregs  = map { "st$_" }  (0 .. 7);
    199 
    200     my @presets;
    201     my $presetc = 0;
    202     my $eflagsmask;
    203     my $eflagsset;
    204     my $fpucwmask;
    205     my $fpucwset;
    206     my $fpuswmask;
    207     my $fpuswset;
    208 
    209     foreach my $preset (split(/\s+/, $presets))
    210     {
    211         if ($preset =~ /^([abcd][lh]|[abcd]x|e[abcd]x)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/)
    212         {
    213             my $name = "preset$presetc";
    214             my $type = $RegTypes{$1};
    215             my $regnum = $RegNums{$1};
    216             my $register = $intregs[$regnum];
    217             my $subtype = $2;
    218             my @values = split(/,/, $3);
    219     
    220             die "Register $1 already used" unless defined($register);
    221 
    222             my $preset = {
    223                 name => $name,
    224                 type => $type,
    225                 subtype => $subtype,
    226                 register => $register
    227             };
    228 
    229             delete($intregs[$regnum]);
    230 
    231             push @presets, $preset;
    232             
    233             print qq|   $ArgTypes{$type} $name = \{ .$subtype = \{|;
    234             
    235             my $valuec = 0;
    236             
    237             foreach my $value (@values)
    238             {
    239                 print qq|,| if $valuec > 0;
    240                 print qq| $value$SubTypeSuffixes{$subtype}|;
    241                 $valuec++;
    242             }
    243             
    244             print qq| \} \};\n|;
    245 
    246             $presetc++;
    247         }
    248         elsif ($preset =~ /^st([0-9]+)\.(ps|pd)\[([^\]]+)\]$/)
    249         {
    250             my $name = "preset$presetc";
    251             my $type = "st";
    252             my $regnum = $1;
    253             my $register = $fpregs[$regnum];
    254             my $subtype = $2;
    255             my @values = split(/,/, $3);
    256 
    257             die "Register st$1 already used" unless defined($register);
    258 
    259             my $preset = {
    260                 name => $name,
    261                 type => $type,
    262                 subtype => $subtype,
    263                 register => $register
    264             };
    265 
    266             delete($fpregs[$regnum]);
    267 
    268             push @presets, $preset;
    269             
    270             print qq|   $ArgTypes{$type} $name = \{ .$subtype = \{|;
    271             
    272             my $valuec = 0;
    273             
    274             foreach my $value (@values)
    275             {
    276                 print qq|,| if $valuec > 0;
    277                 print qq| $value$SubTypeSuffixes{$subtype}|;
    278                 $valuec++;
    279             }
    280             
    281             print qq| \} \};\n|;
    282 
    283             $presetc++;
    284         }
    285         elsif ($preset =~ /^(eflags)\[([^\]]+)\]$/)
    286         {
    287             my $type = $1;
    288             my @values = split(/,/, $2);
    289 
    290             $values[0] = oct($values[0]) if $values[0] =~ /^0/;
    291             $values[1] = oct($values[1]) if $values[1] =~ /^0/;
    292 
    293             $eflagsmask = sprintf "0x%08x", $values[0] ^ 0xffffffff;
    294             $eflagsset = sprintf "0x%08x", $values[1];
    295         }
    296         elsif ($preset =~ /^(fpucw)\[([^\]]+)\]$/)
    297         {
    298             my $type = $1;
    299             my @values = split(/,/, $2);
    300 
    301             $values[0] = oct($values[0]) if $values[0] =~ /^0/;
    302             $values[1] = oct($values[1]) if $values[1] =~ /^0/;
    303 
    304             $fpucwmask = sprintf "0x%04x", $values[0] ^ 0xffff;
    305             $fpucwset = sprintf "0x%04x", $values[1];
    306         }
    307         elsif ($preset =~ /^(fpusw)\[([^\]]+)\]$/)
    308         {
    309             my $type = $1;
    310             my @values = split(/,/, $2);
    311 
    312             $values[0] = oct($values[0]) if $values[0] =~ /^0/;
    313             $values[1] = oct($values[1]) if $values[1] =~ /^0/;
    314 
    315             $fpuswmask = sprintf "0x%04x", $values[0] ^ 0xffff;
    316             $fpuswset = sprintf "0x%04x", $values[1];
    317         }
    318         else
    319         {
    320             die "Can't parse preset $preset";
    321         }
    322     }
    323 
    324     my @args;
    325     my $argc = 0;
    326     
    327     foreach my $arg (split(/\s+/, $args))
    328     {
    329         my $name = "arg$argc";
    330 
    331         if ($arg =~ /^([abcd]l|[abcd]x|e[abcd]x|r8|r16|r32|mm|xmm|m8|m16|m32|m64|m128)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/)
    332         {
    333             my $type = $RegTypes{$1} || $1;
    334             my $regnum = $RegNums{$1};
    335             my $register = $intregs[$regnum] if defined($regnum);
    336             my $subtype = $2;
    337             my @values = split(/,/, $3);
    338             
    339             die "Register $1 already used" if defined($regnum) && !defined($register);
    340 
    341             my $arg = {
    342                 name => $name,
    343                 type => $type,
    344                 subtype => $subtype
    345             };
    346 
    347             if (defined($register))
    348             {
    349                 $arg->{register} = $register;
    350                 delete($intregs[$regnum]);
    351             }
    352 
    353             push @args, $arg;
    354             
    355             print qq|   $ArgTypes{$type} $name = \{ .$subtype = \{|;
    356             
    357             my $valuec = 0;
    358             
    359             foreach my $value (@values)
    360             {
    361                 print qq|,| if $valuec > 0;
    362                 print qq| $value$SubTypeSuffixes{$subtype}|;
    363                 $valuec++;
    364             }
    365 
    366             print qq| \} \};\n|;
    367         }
    368         elsif ($arg =~ /^st([0-9]+)\.(ps|pd)\[([^\]]+)\]$/)
    369         {
    370             my $type = "st";
    371             my $regnum = $1;
    372             my $register = $fpregs[$regnum] if defined($regnum);
    373             my $subtype = $2;
    374             my @values = split(/,/, $3);
    375             
    376             die "Register st$1 already used" if defined($regnum) && !defined($register);
    377 
    378             my $arg = {
    379                 name => $name,
    380                 type => $type,
    381                 subtype => $subtype
    382             };
    383 
    384             if (defined($register))
    385             {
    386                 $arg->{register} = $register;
    387                 delete($fpregs[$regnum]);
    388             }
    389 
    390             push @args, $arg;
    391             
    392             print qq|   $ArgTypes{$type} $name = \{ .$subtype = \{|;
    393             
    394             my $valuec = 0;
    395             
    396             foreach my $value (@values)
    397             {
    398                 print qq|,| if $valuec > 0;
    399                 print qq| $value$SubTypeSuffixes{$subtype}|;
    400                 $valuec++;
    401             }
    402 
    403             print qq| \} \};\n|;
    404         }
    405         elsif ($arg =~ /^(imm8|imm16|imm32)\[([^\]]+)\]$/)
    406         {
    407             my $type = $1;
    408             my $value = $2;
    409             
    410             my $arg = {
    411                 type => $type,
    412                 value => $value
    413             };
    414 
    415             push @args, $arg;
    416         }
    417         else
    418         {
    419             die "Can't parse argument $arg";
    420         }
    421 
    422         $argc++;
    423     }
    424     
    425     foreach my $arg (@presets, @args)
    426     {
    427         if ($arg->{type} =~ /^(r8|r16|r32|m8|m16|m32)$/)
    428         {
    429             while (!exists($arg->{register}) || !defined($arg->{register}))
    430             {
    431                 $arg->{register} = shift @intregs;
    432             }
    433 
    434             $arg->{register} = $arg->{register}->{$arg->{type}};
    435         }
    436         elsif ($arg->{type} =~ /^(mm|m64)$/)
    437         {
    438             $arg->{register} = shift @mmregs;
    439         }
    440         elsif ($arg->{type} =~ /^(xmm|m128)$/)
    441         {
    442             $arg->{register} = shift @xmmregs;
    443         }
    444         elsif ($arg->{type} =~ /^st$/)
    445         {
    446             while (!exists($arg->{register}) || !defined($arg->{register}))
    447             {
    448                 $arg->{register} = shift @fpregs;
    449             }
    450         }
    451     }
    452 
    453     my @results;
    454     my $resultc = 0;
    455     
    456     foreach my $result (split(/\s+/, $results))
    457     {
    458         my $name = "result$resultc";
    459     
    460         if ($result =~ /^(\d+)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/)
    461         {
    462             my $index = $1;
    463             my $type = $args[$index]->{type};
    464             my $subtype = $2;
    465             my @values = split(/,/, $3);
    466             
    467             die "Argument $index not specified" unless exists($args[$index]);
    468 
    469             my $result = {
    470                 name => $name,
    471                 type => $type,
    472                 subtype => $subtype,
    473                 arg => $args[$index],
    474                 register => $args[$index]->{register},
    475                 values => [ @values ]
    476             };
    477 
    478             push @results, $result;
    479 
    480             print qq|   $ArgTypes{$type} $name|;
    481             print qq| = arg$index| if $type =~ /^m(8|16|32|64|128)$/;
    482             print qq|;\n|;
    483 
    484             $args[$index]->{result} = $result;
    485         }
    486         elsif ($result =~ /^([abcd][lh]|[abcd]x|e[abcd]x)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/)
    487         {
    488             my $register = $1;
    489             my $type = $RegTypes{$register};
    490             my $subtype = $2;
    491             my @values = split(/,/, $3);
    492                         
    493             my $result = {
    494                 name => $name,
    495                 type => $type,
    496                 subtype => $subtype,
    497                 register => $register,
    498                 values => [ @values ]
    499             };
    500 
    501             push @results, $result;
    502 
    503             print qq|   $ArgTypes{$type} $name;\n|;
    504         }
    505         elsif ($result =~ /^(st[0-9]+)\.(ps|pd)\[([^\]]+)\]$/)
    506         {
    507             my $register = $1;
    508             my $type = "st";
    509             my $subtype = $2;
    510             my @values = split(/,/, $3);
    511                         
    512             my $result = {
    513                 name => $name,
    514                 type => $type,
    515                 subtype => $subtype,
    516                 register => $register,
    517                 values => [ @values ]
    518             };
    519 
    520             push @results, $result;
    521 
    522             print qq|   $ArgTypes{$type} $name;\n|;
    523         }
    524         elsif ($result =~ /^eflags\[([^\]]+)\]$/)
    525         {
    526             my @values = split(/,/, $1);
    527             
    528             $values[0] = oct($values[0]) if $values[0] =~ /^0/;
    529             $values[1] = oct($values[1]) if $values[1] =~ /^0/;
    530             
    531             my $result = {
    532                 name => $name,
    533                 type => "eflags",
    534                 subtype => "ud",
    535                 values => [ map { sprintf "0x%08x", $_ } @values ]
    536             };
    537 
    538             push @results, $result;
    539             
    540             print qq|   $ArgTypes{eflags} $name;\n|;
    541 
    542             if (!defined($eflagsmask) && !defined($eflagsset))
    543             {
    544                 $eflagsmask = sprintf "0x%08x", $values[0] ^ 0xffffffff;
    545                 $eflagsset = sprintf "0x%08x", $values[0] & ~$values[1];
    546             }
    547         }
    548         elsif ($result =~ /^fpucw\[([^\]]+)\]$/)
    549         {
    550             my @values = split(/,/, $1);
    551             
    552             $values[0] = oct($values[0]) if $values[0] =~ /^0/;
    553             $values[1] = oct($values[1]) if $values[1] =~ /^0/;
    554             
    555             my $result = {
    556                 name => $name,
    557                 type => "fpucw",
    558                 subtype => "ud",
    559                 values => [ map { sprintf "0x%04x", $_ } @values ]
    560             };
    561 
    562             push @results, $result;
    563             
    564             print qq|   $ArgTypes{fpucw} $name;\n|;
    565 
    566             if (!defined($fpucwmask) && !defined($fpucwset))
    567             {
    568                 $fpucwmask = sprintf "0x%04x", $values[0] ^ 0xffff;
    569                 $fpucwset = sprintf "0x%04x", $values[0] & ~$values[1];
    570             }
    571         }
    572         elsif ($result =~ /^fpusw\[([^\]]+)\]$/)
    573         {
    574             my @values = split(/,/, $1);
    575             
    576             $values[0] = oct($values[0]) if $values[0] =~ /^0/;
    577             $values[1] = oct($values[1]) if $values[1] =~ /^0/;
    578             
    579             my $result = {
    580                 name => $name,
    581                 type => "fpusw",
    582                 subtype => "ud",
    583                 values => [ map { sprintf "0x%04x", $_ } @values ]
    584             };
    585 
    586             push @results, $result;
    587             
    588             print qq|   $ArgTypes{fpusw} $name;\n|;
    589 
    590             if (!defined($fpuswmask) && !defined($fpuswset))
    591             {
    592                 $fpuswmask = sprintf "0x%04x", $values[0] ^ 0xffff;
    593                 $fpuswset = sprintf "0x%04x", $values[0] & ~$values[1];
    594             }
    595         }
    596         else
    597         {
    598             die "Can't parse result $result";
    599         }
    600         
    601         $resultc++;
    602     }
    603     
    604     my $argnum = 0;
    605 
    606     foreach my $result (@results)
    607     {
    608         if ($result->{type} eq "xmm")
    609         {
    610             $result->{argnuml} = $argnum++;
    611             $result->{argnumh} = $argnum++;
    612         }
    613         else
    614         {
    615             $result->{argnum} = $argnum++;
    616         }
    617     }
    618     
    619     foreach my $arg (@presets, @args)
    620     {
    621         if (defined($arg->{name}))
    622         {
    623             if ($arg->{type} eq "xmm")
    624             {
    625                 $arg->{argnuml} = $argnum++;
    626                 $arg->{argnumh} = $argnum++;
    627             }
    628             else
    629             {
    630                 $arg->{argnum} = $argnum++;
    631             }
    632         }
    633     }
    634 
    635     my $stateargnum = $argnum++;
    636 
    637     print qq|   char state\[108\];\n|;
    638     print qq|\n|;
    639     print qq|   if (sigsetjmp(catchpoint, 1) == 0)\n|;
    640     print qq|   \{\n|;
    641     print qq|      asm\(\n|;
    642     print qq|         \"fsave %$stateargnum\\n\"\n|;
    643     
    644     my @fpargs;
    645 
    646     foreach my $arg (@presets, @args)
    647     {
    648         if ($arg->{type} eq "r8")
    649         {
    650             print qq|         \"movb %$arg->{argnum}, %%$arg->{register}\\n\"\n|;
    651         }
    652         elsif ($arg->{type} eq "r16")
    653         {
    654             print qq|         \"movw %$arg->{argnum}, %%$arg->{register}\\n\"\n|;
    655         }
    656         elsif ($arg->{type} eq "r32")
    657         {
    658             print qq|         \"movl %$arg->{argnum}, %%$arg->{register}\\n\"\n|;
    659         }
    660         elsif ($arg->{type} eq "mm")
    661         {
    662             print qq|         \"movq %$arg->{argnum}, %%$arg->{register}\\n\"\n|;
    663         }
    664         elsif ($arg->{type} eq "xmm")
    665         {
    666             print qq|         \"movlps %$arg->{argnuml}, %%$arg->{register}\\n\"\n|;
    667             print qq|         \"movhps %$arg->{argnumh}, %%$arg->{register}\\n\"\n|;
    668         }
    669         elsif ($arg->{type} eq "st")
    670         {
    671             $fpargs[$RegNums{$arg->{register}}] = $arg;
    672         }
    673     }
    674     
    675     foreach my $arg (reverse @fpargs)
    676     {
    677         if (defined($arg))
    678         {
    679             if ($arg->{subtype} eq "ps")
    680             {
    681                 print qq|         \"flds %$arg->{argnum}\\n\"\n|;
    682             }
    683             elsif ($arg->{subtype} eq "pd")
    684             {
    685                 print qq|         \"fldl %$arg->{argnum}\\n\"\n|;
    686             }
    687         }
    688         else
    689         {
    690             print qq|         \"fldz\\n\"\n|;
    691         }
    692     }
    693 
    694     if (defined($eflagsmask) || defined($eflagsset))
    695     {
    696         print qq|         \"pushfl\\n\"\n|;
    697         print qq|         \"andl \$$eflagsmask, (%%esp)\\n\"\n| if defined($eflagsmask);
    698         print qq|         \"orl \$$eflagsset, (%%esp)\\n\"\n| if defined($eflagsset);
    699         print qq|         \"popfl\\n\"\n|;
    700     }
    701 
    702     if (defined($fpucwmask) || defined($fpucwset))
    703     {
    704         print qq|         \"subl \$2, %%esp\\n\"\n|;
    705         print qq|         \"fstcw (%%esp)\\n\"\n|;
    706         print qq|         \"andw \$$fpucwmask, (%%esp)\\n\"\n| if defined($fpucwmask);
    707         print qq|         \"orw \$$fpucwset, (%%esp)\\n\"\n| if defined($fpucwset);
    708         print qq|         \"fldcw (%%esp)\\n\"\n|;
    709         print qq|         \"addl \$2, %%esp\\n\"\n|;
    710     }
    711 
    712     print qq|         \"$insn|;
    713     
    714     my $prefix = " ";
    715     
    716     foreach my $arg (@args)
    717     {
    718         next if $arg->{type} eq "eflags";
    719 
    720         if ($arg->{type} =~ /^(r8|r16|r32|mm|xmm)$/)
    721         {
    722             print qq|$prefix%%$arg->{register}|;
    723         }
    724         elsif ($arg->{type} =~ /^st$/)
    725         {
    726             my $register = $arg->{register};
    727 
    728             $register =~ s/st(\d+)/st\($1\)/;
    729 
    730             print qq|$prefix%%$register|;
    731         }
    732         elsif ($arg->{type} =~ /^(m(8|16|32|64|128))$/)
    733         {
    734             if (exists($arg->{result}))
    735             {
    736                 print qq|$prefix%$arg->{result}->{argnum}|;
    737             }
    738             else
    739             {
    740                 print qq|$prefix%$arg->{argnum}|;
    741             }
    742         }
    743         elsif ($arg->{type} =~ /^imm(8|16|32)$/)
    744         {
    745             print qq|$prefix\$$arg->{value}|;
    746         }
    747 
    748         $prefix = ", ";
    749     }
    750 
    751     print qq|\\n\"\n|;
    752 
    753     my @fpresults;
    754 
    755     foreach my $result (@results)
    756     {
    757         if ($result->{type} eq "r8")
    758         {
    759             print qq|         \"movb %%$result->{register}, %$result->{argnum}\\n\"\n|;
    760         }
    761         elsif ($result->{type} eq "r16")
    762         {
    763             print qq|         \"movw %%$result->{register}, %$result->{argnum}\\n\"\n|;
    764         }
    765         elsif ($result->{type} eq "r32")
    766         {
    767             print qq|         \"movl %%$result->{register}, %$result->{argnum}\\n\"\n|;
    768         }
    769         elsif ($result->{type} eq "mm")
    770         {
    771             print qq|         \"movq %%$result->{register}, %$result->{argnum}\\n\"\n|;
    772         }
    773         elsif ($result->{type} eq "xmm")
    774         {
    775             print qq|         \"movlps %%$result->{register}, %$result->{argnuml}\\n\"\n|;
    776             print qq|         \"movhps %%$result->{register}, %$result->{argnumh}\\n\"\n|;
    777         }
    778         elsif ($result->{type} eq "st")
    779         {
    780             $fpresults[$RegNums{$result->{register}}] = $result;
    781         }
    782         elsif ($result->{type} eq "eflags")
    783         {
    784             print qq|         \"pushfl\\n\"\n|;
    785             print qq|         \"popl %$result->{argnum}\\n\"\n|;
    786         }
    787         elsif ($result->{type} eq "fpucw")
    788         {
    789             print qq|         \"fstcw %$result->{argnum}\\n\"\n|;
    790         }
    791         elsif ($result->{type} eq "fpusw")
    792         {
    793             print qq|         \"fstsw %$result->{argnum}\\n\"\n|;
    794         }
    795     }
    796     
    797     foreach my $result (@fpresults)
    798     {
    799         if (defined($result))
    800         {
    801             if ($result->{subtype} eq "ps")
    802             {
    803                 print qq|         \"fstps %$result->{argnum}\\n\"\n|;
    804             }
    805             elsif ($result->{subtype} eq "pd")
    806             {
    807                 print qq|         \"fstpl %$result->{argnum}\\n\"\n|;
    808             }
    809         }
    810         else
    811         {
    812             print qq|         \"fincstp\\n\"\n|;
    813         }
    814     }
    815 
    816     print qq|         \"frstor %$stateargnum\\n\"\n|;
    817     print qq|         \"cld\\n\"\n|;
    818     
    819     print qq|         :|;
    820 
    821     $prefix = " ";
    822 
    823     foreach my $result (@results)
    824     {
    825         if ($result->{type} eq "xmm")
    826         {
    827             print qq|$prefix\"=m\" \($result->{name}.uq[0]\), \"=m\" \($result->{name}.uq[1]\)|;
    828         }
    829         else
    830         {
    831             print qq|$prefix\"=m\" \($result->{name}\)|;
    832         }
    833 
    834         $prefix = ", ";
    835     }
    836 
    837     print qq|\n|;
    838     
    839     $prefix = "         : ";
    840     
    841     foreach my $arg (@presets, @args)
    842     {
    843         if (defined($arg->{name}))
    844         {
    845             if ($arg->{type} eq "xmm")
    846             {
    847                 print qq|$prefix\"m\" \($arg->{name}.uq[0]\), \"m\" \($arg->{name}.uq[1]\)|;
    848             }
    849             else
    850             {
    851                 print qq|$prefix\"m\" \($arg->{name}\)|;
    852             }
    853 
    854             $prefix = ", ";
    855         }
    856     }
    857 
    858     print qq|$prefix\"m\" \(state[0]\)\n|;
    859 
    860     $prefix = "         : ";
    861 
    862     foreach my $arg (@presets, @args)
    863     {
    864         if ($arg->{register} && $arg->{type} ne "st")
    865         {
    866             print qq|$prefix\"$arg->{register}\"|;
    867             $prefix = ", ";
    868         }
    869     }
    870 
    871     print qq|\n|;
    872     
    873     print qq|      \);\n|;                          
    874     print qq|\n|;
    875     
    876     if (@results)
    877     {
    878         print qq|      if \(|;
    879         
    880         $prefix = "";
    881         
    882         foreach my $result (@results)
    883         {
    884             my $type = $result->{type};
    885             my $subtype = $result->{subtype};
    886             my $suffix = $SubTypeSuffixes{$subtype};
    887             my @values = @{$result->{values}};
    888             
    889             if ($type eq "eflags")
    890             {
    891                 print qq|${prefix}\($result->{name}.ud[0] & $values[0]UL\) == $values[1]UL|;
    892             }
    893             elsif ($type =~ /^fpu[cs]w$/)
    894             {
    895                 print qq|${prefix}\($result->{name}.uw[0] & $values[0]\) == $values[1]|;
    896             }
    897             else
    898             {
    899                 foreach my $value (0 .. $#values)
    900                 {
    901                     if ($subtype eq "ps")
    902                     {
    903                         print qq|${prefix}eq_float($result->{name}.$subtype\[$value\], $values[$value]$suffix)|;
    904                     }
    905                     elsif ($subtype eq "pd")
    906                     {
    907                         print qq|${prefix}eq_double($result->{name}.$subtype\[$value\], $values[$value]$suffix)|;
    908                     }
    909                     else
    910                     {
    911                         print qq|${prefix}$result->{name}.$subtype\[$value\] == $values[$value]$suffix|;
    912                     }
    913                     
    914                     $prefix = " && ";
    915                 }
    916             }
    917             
    918             $prefix = " &&\n          ";
    919         }
    920         
    921         print qq| \)\n|;
    922         print qq|      \{\n|;
    923         print qq|         printf("$test ... ok\\n");\n|;
    924         print qq|      \}\n|;
    925         print qq|      else\n|;
    926         print qq|      \{\n|;
    927         print qq|         printf("$test ... not ok\\n");\n|;
    928         
    929         foreach my $result (@results)
    930         {
    931             my $type = $result->{type};
    932             my $subtype = $result->{subtype};
    933             my $suffix = $SubTypeSuffixes{$subtype};
    934             my @values = @{$result->{values}};
    935             
    936             if ($type eq "eflags")
    937             {
    938                 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|;
    939             }
    940             elsif ($type =~ /^fpu[cs]w$/)
    941             {
    942                 print qq|         printf("  $type & 0x%x = 0x%x (expected 0x%x)\\n", $values[0], $result->{name}.uw\[0\] & $values[0], $values[1]);\n|;
    943             }
    944             else
    945             {
    946                 foreach my $value (0 .. $#values)
    947                 {
    948                     print qq|         printf("  $result->{name}.$subtype\[$value\] = $SubTypeFormats{$subtype} (expected $SubTypeFormats{$subtype})\\n", $result->{name}.$subtype\[$value\], $values[$value]$suffix);\n|;
    949                 }
    950             }
    951         }
    952         
    953         print qq|      \}\n|;
    954     }
    955     else
    956     {
    957         print qq|      printf("$test ... ok\\n");\n|;
    958     }
    959 
    960     print qq|   \}\n|;
    961     print qq|   else\n|;
    962     print qq|   \{\n|;
    963     print qq|      printf("$test ... failed\\n");\n|;
    964     print qq|   \}\n|;
    965     print qq|\n|;
    966     print qq|   return;\n|;
    967     print qq|\}\n|;
    968     print qq|\n|;
    969 }
    970 
    971 print qq|int main(int argc, char **argv)\n|;
    972 print qq|\{\n|;
    973 print qq|   signal(SIGILL, handle_sigill);\n|;
    974 print qq|\n|;
    975 
    976 foreach my $test (@tests)
    977 {
    978     print qq|   $test();\n|;
    979 }
    980 
    981 print qq|\n|;
    982 print qq|   exit(0);\n|;
    983 print qq|\}\n|;
    984 
    985 exit 0;
    986