]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/none/tests/x86/gen_insn_test.pl
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / none / tests / x86 / gen_insn_test.pl
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;