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