1#!/usr/bin/perl
2
3use 5.006;
4use strict;
5use warnings;
6
7our %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
24our %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
37our %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
50our %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
63our %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
70our @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
81print <<EOF;
82#include <math.h>
83#include <setjmp.h>
84#include <signal.h>
85#include <stdio.h>
86#include <stdlib.h>
87
88typedef union {
89  char sb[1];
90  unsigned char ub[1];
91} reg8_t;
92
93typedef union {
94  char sb[2];
95  unsigned char ub[2];
96  short sw[1];
97  unsigned short uw[1];
98} reg16_t;
99
100typedef 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
110typedef 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
123typedef 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
136static sigjmp_buf catchpoint;
137
138static void handle_sigill(int signum)
139{
140   siglongjmp(catchpoint, 1);
141}
142
143__attribute__((unused))
144static 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))
150static int eq_double(double d1, double d2)
151{
152   return d1 == d2 || fabs(d1 - d2) < fabs(d1) * 1.5 * pow(2,-12);
153}
154
155EOF
156
157my %tests;
158my @tests;
159
160while (<>)
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
971print qq|int main(int argc, char **argv)\n|;
972print qq|\{\n|;
973print qq|   signal(SIGILL, handle_sigill);\n|;
974print qq|\n|;
975
976foreach my $test (@tests)
977{
978    print qq|   $test();\n|;
979}
980
981print qq|\n|;
982print qq|   exit(0);\n|;
983print qq|\}\n|;
984
985exit 0;
986