24 our %SubTypeFormats = (
37 our %SubTypeSuffixes = (
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,
59 st0
=> 0, st1
=> 1, st2
=> 2, st3
=> 3,
60 st4
=> 4, st5
=> 5, st6
=> 6, st7
=> 7
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"
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" },
104 unsigned short uw[2];
106 unsigned long int ud[1];
114 unsigned short uw[4];
116 unsigned long int ud[2];
118 unsigned long long int uq[1];
121 } reg64_t __attribute__ ((aligned (8)));
125 unsigned char ub[16];
127 unsigned short uw[8];
129 unsigned long int ud[4];
131 unsigned long long int uq[2];
134 } reg128_t __attribute__ ((aligned (16)));
136 static sigjmp_buf catchpoint;
138 static void handle_sigill(int signum)
140 siglongjmp(catchpoint, 1);
143 __attribute__((unused))
144 static int eq_float(float f1, float f2)
146 return f1 == f2 || fabsf(f1 - f2) < fabsf(f1) * 1.5 * pow(2,-12);
149 __attribute__((unused))
150 static int eq_double(double d1, double d2)
152 return d1 == d2 || fabs(d1 - d2) < fabs(d1) * 1.5 * pow(2,-12);
169 if (/^(\S+)\s+(?:(\S+(?:\s+\S+)*)\s+:\s+)?((?:\S+\s+)*?)(?:=>\s+(\S+(?:\s+\S+)*))?$/)
176 # print STDERR "insn: $insn\n";
177 # print STDERR "presets: $presets\n";
178 # print STDERR "args: $args\n";
179 # print STDERR "results: $results\n";
183 die "Can't parse test $_";
188 my $test = "${insn}_$tests{$insn}";
192 print qq|static void
$test(void
)\n|;
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);
209 foreach my $preset (split(/\s+/, $presets))
211 if ($preset =~ /^([abcd][lh]|[abcd]x|e[abcd]x)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/)
213 my $name = "preset$presetc";
214 my $type = $RegTypes{$1};
215 my $regnum = $RegNums{$1};
216 my $register = $intregs[$regnum];
218 my @values = split(/,/, $3);
220 die "Register $1 already used" unless defined($register);
226 register
=> $register
229 delete($intregs[$regnum]);
231 push @presets, $preset;
233 print qq| $ArgTypes{$type} $name = \
{ .$subtype = \
{|;
237 foreach my $value (@values)
239 print qq|,| if $valuec > 0;
240 print qq| $value$SubTypeSuffixes{$subtype}|;
248 elsif ($preset =~ /^st([0-9]+)\.(ps|pd)\[([^\]]+)\]$/)
250 my $name = "preset$presetc";
253 my $register = $fpregs[$regnum];
255 my @values = split(/,/, $3);
257 die "Register st$1 already used" unless defined($register);
263 register
=> $register
266 delete($fpregs[$regnum]);
268 push @presets, $preset;
270 print qq| $ArgTypes{$type} $name = \
{ .$subtype = \
{|;
274 foreach my $value (@values)
276 print qq|,| if $valuec > 0;
277 print qq| $value$SubTypeSuffixes{$subtype}|;
285 elsif ($preset =~ /^(eflags)\[([^\]]+)\]$/)
288 my @values = split(/,/, $2);
290 $values[0] = oct($values[0]) if $values[0] =~ /^0/;
291 $values[1] = oct($values[1]) if $values[1] =~ /^0/;
293 $eflagsmask = sprintf "0x%08x", $values[0] ^ 0xffffffff;
294 $eflagsset = sprintf "0x%08x", $values[1];
296 elsif ($preset =~ /^(fpucw)\[([^\]]+)\]$/)
299 my @values = split(/,/, $2);
301 $values[0] = oct($values[0]) if $values[0] =~ /^0/;
302 $values[1] = oct($values[1]) if $values[1] =~ /^0/;
304 $fpucwmask = sprintf "0x%04x", $values[0] ^ 0xffff;
305 $fpucwset = sprintf "0x%04x", $values[1];
307 elsif ($preset =~ /^(fpusw)\[([^\]]+)\]$/)
310 my @values = split(/,/, $2);
312 $values[0] = oct($values[0]) if $values[0] =~ /^0/;
313 $values[1] = oct($values[1]) if $values[1] =~ /^0/;
315 $fpuswmask = sprintf "0x%04x", $values[0] ^ 0xffff;
316 $fpuswset = sprintf "0x%04x", $values[1];
320 die "Can't parse preset $preset";
327 foreach my $arg (split(/\s+/, $args))
329 my $name = "arg$argc";
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)\[([^\]]+)\]$/)
333 my $type = $RegTypes{$1} || $1;
334 my $regnum = $RegNums{$1};
335 my $register = $intregs[$regnum] if defined($regnum);
337 my @values = split(/,/, $3);
339 die "Register $1 already used" if defined($regnum) && !defined($register);
347 if (defined($register))
349 $arg->{register
} = $register;
350 delete($intregs[$regnum]);
355 print qq| $ArgTypes{$type} $name = \
{ .$subtype = \
{|;
359 foreach my $value (@values)
361 print qq|,| if $valuec > 0;
362 print qq| $value$SubTypeSuffixes{$subtype}|;
368 elsif ($arg =~ /^st([0-9]+)\.(ps|pd)\[([^\]]+)\]$/)
372 my $register = $fpregs[$regnum] if defined($regnum);
374 my @values = split(/,/, $3);
376 die "Register st$1 already used" if defined($regnum) && !defined($register);
384 if (defined($register))
386 $arg->{register
} = $register;
387 delete($fpregs[$regnum]);
392 print qq| $ArgTypes{$type} $name = \
{ .$subtype = \
{|;
396 foreach my $value (@values)
398 print qq|,| if $valuec > 0;
399 print qq| $value$SubTypeSuffixes{$subtype}|;
405 elsif ($arg =~ /^(imm8|imm16|imm32)\[([^\]]+)\]$/)
419 die "Can't parse argument $arg";
425 foreach my $arg (@presets, @args)
427 if ($arg->{type
} =~ /^(r8|r16|r32|m8|m16|m32)$/)
429 while (!exists($arg->{register
}) || !defined($arg->{register
}))
431 $arg->{register
} = shift @intregs;
434 $arg->{register
} = $arg->{register
}->{$arg->{type
}};
436 elsif ($arg->{type
} =~ /^(mm|m64)$/)
438 $arg->{register
} = shift @mmregs;
440 elsif ($arg->{type
} =~ /^(xmm|m128)$/)
442 $arg->{register
} = shift @xmmregs;
444 elsif ($arg->{type
} =~ /^st$/)
446 while (!exists($arg->{register
}) || !defined($arg->{register
}))
448 $arg->{register
} = shift @fpregs;
456 foreach my $result (split(/\s+/, $results))
458 my $name = "result$resultc";
460 if ($result =~ /^(\d+)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/)
463 my $type = $args[$index]->{type
};
465 my @values = split(/,/, $3);
467 die "Argument $index not specified" unless exists($args[$index]);
473 arg
=> $args[$index],
474 register
=> $args[$index]->{register
},
475 values => [ @values ]
478 push @results, $result;
480 print qq| $ArgTypes{$type} $name|;
481 print qq| = arg
$index| if $type =~ /^m(8|16|32|64|128)$/;
484 $args[$index]->{result
} = $result;
486 elsif ($result =~ /^([abcd][lh]|[abcd]x|e[abcd]x)\.(sb|ub|sw|uw|sd|ud|sq|uq|ps|pd)\[([^\]]+)\]$/)
489 my $type = $RegTypes{$register};
491 my @values = split(/,/, $3);
497 register
=> $register,
498 values => [ @values ]
501 push @results, $result;
503 print qq| $ArgTypes{$type} $name;\n|;
505 elsif ($result =~ /^(st[0-9]+)\.(ps|pd)\[([^\]]+)\]$/)
510 my @values = split(/,/, $3);
516 register
=> $register,
517 values => [ @values ]
520 push @results, $result;
522 print qq| $ArgTypes{$type} $name;\n|;
524 elsif ($result =~ /^eflags\[([^\]]+)\]$/)
526 my @values = split(/,/, $1);
528 $values[0] = oct($values[0]) if $values[0] =~ /^0/;
529 $values[1] = oct($values[1]) if $values[1] =~ /^0/;
535 values => [ map { sprintf "0x%08x", $_ } @values ]
538 push @results, $result;
540 print qq| $ArgTypes{eflags
} $name;\n|;
542 if (!defined($eflagsmask) && !defined($eflagsset))
544 $eflagsmask = sprintf "0x%08x", $values[0] ^ 0xffffffff;
545 $eflagsset = sprintf "0x%08x", $values[0] & ~$values[1];
548 elsif ($result =~ /^fpucw\[([^\]]+)\]$/)
550 my @values = split(/,/, $1);
552 $values[0] = oct($values[0]) if $values[0] =~ /^0/;
553 $values[1] = oct($values[1]) if $values[1] =~ /^0/;
559 values => [ map { sprintf "0x%04x", $_ } @values ]
562 push @results, $result;
564 print qq| $ArgTypes{fpucw
} $name;\n|;
566 if (!defined($fpucwmask) && !defined($fpucwset))
568 $fpucwmask = sprintf "0x%04x", $values[0] ^ 0xffff;
569 $fpucwset = sprintf "0x%04x", $values[0] & ~$values[1];
572 elsif ($result =~ /^fpusw\[([^\]]+)\]$/)
574 my @values = split(/,/, $1);
576 $values[0] = oct($values[0]) if $values[0] =~ /^0/;
577 $values[1] = oct($values[1]) if $values[1] =~ /^0/;
583 values => [ map { sprintf "0x%04x", $_ } @values ]
586 push @results, $result;
588 print qq| $ArgTypes{fpusw
} $name;\n|;
590 if (!defined($fpuswmask) && !defined($fpuswset))
592 $fpuswmask = sprintf "0x%04x", $values[0] ^ 0xffff;
593 $fpuswset = sprintf "0x%04x", $values[0] & ~$values[1];
598 die "Can't parse result $result";
606 foreach my $result (@results)
608 if ($result->{type
} eq "xmm")
610 $result->{argnuml
} = $argnum++;
611 $result->{argnumh
} = $argnum++;
615 $result->{argnum
} = $argnum++;
619 foreach my $arg (@presets, @args)
621 if (defined($arg->{name
}))
623 if ($arg->{type
} eq "xmm")
625 $arg->{argnuml
} = $argnum++;
626 $arg->{argnumh
} = $argnum++;
630 $arg->{argnum
} = $argnum++;
635 my $stateargnum = $argnum++;
637 print qq| char
state\
[108\
];\n|;
639 print qq| if (sigsetjmp
(catchpoint
, 1) == 0)\n|;
642 print qq| \"fsave
%$stateargnum\\n
\"\n|;
646 foreach my $arg (@presets, @args)
648 if ($arg->{type
} eq "r8")
650 print qq| \"movb
%$arg->{argnum
}, %%$arg->{register
}\\n
\"\n|;
652 elsif ($arg->{type
} eq "r16")
654 print qq| \"movw
%$arg->{argnum
}, %%$arg->{register
}\\n
\"\n|;
656 elsif ($arg->{type
} eq "r32")
658 print qq| \"movl
%$arg->{argnum
}, %%$arg->{register
}\\n
\"\n|;
660 elsif ($arg->{type
} eq "mm")
662 print qq| \"movq
%$arg->{argnum
}, %%$arg->{register
}\\n
\"\n|;
664 elsif ($arg->{type
} eq "xmm")
666 print qq| \"movlps
%$arg->{argnuml
}, %%$arg->{register
}\\n
\"\n|;
667 print qq| \"movhps
%$arg->{argnumh
}, %%$arg->{register
}\\n
\"\n|;
669 elsif ($arg->{type
} eq "st")
671 $fpargs[$RegNums{$arg->{register
}}] = $arg;
675 foreach my $arg (reverse @fpargs)
679 if ($arg->{subtype
} eq "ps")
681 print qq| \"flds
%$arg->{argnum
}\\n
\"\n|;
683 elsif ($arg->{subtype
} eq "pd")
685 print qq| \"fldl
%$arg->{argnum
}\\n
\"\n|;
690 print qq| \"fldz
\\n
\"\n|;
694 if (defined($eflagsmask) || defined($eflagsset))
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|;
702 if (defined($fpucwmask) || defined($fpucwset))
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|;
716 foreach my $arg (@args)
718 next if $arg->{type
} eq "eflags";
720 if ($arg->{type
} =~ /^(r8|r16|r32|mm|xmm)$/)
722 print qq|$prefix%%$arg->{register
}|;
724 elsif ($arg->{type
} =~ /^st$/)
726 my $register = $arg->{register
};
728 $register =~ s/st(\d+)/st\($1\)/;
730 print qq|$prefix%%$register|;
732 elsif ($arg->{type
} =~ /^(m(8|16|32|64|128))$/)
734 if (exists($arg->{result
}))
736 print qq|$prefix%$arg->{result
}->{argnum
}|;
740 print qq|$prefix%$arg->{argnum
}|;
743 elsif ($arg->{type
} =~ /^imm(8|16|32)$/)
745 print qq|$prefix\
$$arg->{value
}|;
755 foreach my $result (@results)
757 if ($result->{type
} eq "r8")
759 print qq| \"movb
%%$result->{register
}, %$result->{argnum
}\\n
\"\n|;
761 elsif ($result->{type
} eq "r16")
763 print qq| \"movw
%%$result->{register
}, %$result->{argnum
}\\n
\"\n|;
765 elsif ($result->{type
} eq "r32")
767 print qq| \"movl
%%$result->{register
}, %$result->{argnum
}\\n
\"\n|;
769 elsif ($result->{type
} eq "mm")
771 print qq| \"movq
%%$result->{register
}, %$result->{argnum
}\\n
\"\n|;
773 elsif ($result->{type
} eq "xmm")
775 print qq| \"movlps
%%$result->{register
}, %$result->{argnuml
}\\n
\"\n|;
776 print qq| \"movhps
%%$result->{register
}, %$result->{argnumh
}\\n
\"\n|;
778 elsif ($result->{type
} eq "st")
780 $fpresults[$RegNums{$result->{register
}}] = $result;
782 elsif ($result->{type
} eq "eflags")
784 print qq| \"pushfl
\\n
\"\n|;
785 print qq| \"popl
%$result->{argnum
}\\n
\"\n|;
787 elsif ($result->{type
} eq "fpucw")
789 print qq| \"fstcw
%$result->{argnum
}\\n
\"\n|;
791 elsif ($result->{type
} eq "fpusw")
793 print qq| \"fstsw
%$result->{argnum
}\\n
\"\n|;
797 foreach my $result (@fpresults)
799 if (defined($result))
801 if ($result->{subtype
} eq "ps")
803 print qq| \"fstps
%$result->{argnum
}\\n
\"\n|;
805 elsif ($result->{subtype
} eq "pd")
807 print qq| \"fstpl
%$result->{argnum
}\\n
\"\n|;
812 print qq| \"fincstp
\\n
\"\n|;
816 print qq| \"frstor
%$stateargnum\\n
\"\n|;
817 print qq| \"cld
\\n
\"\n|;
823 foreach my $result (@results)
825 if ($result->{type
} eq "xmm")
827 print qq|$prefix\"=m
\" \
($result->{name
}.uq
[0]\
), \"=m
\" \
($result->{name
}.uq
[1]\
)|;
831 print qq|$prefix\"=m
\" \
($result->{name
}\
)|;
841 foreach my $arg (@presets, @args)
843 if (defined($arg->{name
}))
845 if ($arg->{type
} eq "xmm")
847 print qq|$prefix\"m
\" \
($arg->{name
}.uq
[0]\
), \"m
\" \
($arg->{name
}.uq
[1]\
)|;
851 print qq|$prefix\"m
\" \
($arg->{name
}\
)|;
858 print qq|$prefix\"m
\" \
(state[0]\
)\n|;
862 foreach my $arg (@presets, @args)
864 if ($arg->{register
} && $arg->{type
} ne "st")
866 print qq|$prefix\"$arg->{register
}\"|;
882 foreach my $result (@results)
884 my $type = $result->{type
};
885 my $subtype = $result->{subtype
};
886 my $suffix = $SubTypeSuffixes{$subtype};
887 my @values = @
{$result->{values}};
889 if ($type eq "eflags")
891 print qq|${prefix
}\
($result->{name
}.ud
[0] & $values[0]UL\
) == $values[1]UL
|;
893 elsif ($type =~ /^fpu[cs]w$/)
895 print qq|${prefix
}\
($result->{name
}.uw
[0] & $values[0]\
) == $values[1]|;
899 foreach my $value (0 .. $#values)
901 if ($subtype eq "ps")
903 print qq|${prefix
}eq_float
($result->{name
}.$subtype\
[$value\
], $values[$value]$suffix)|;
905 elsif ($subtype eq "pd")
907 print qq|${prefix
}eq_double
($result->{name
}.$subtype\
[$value\
], $values[$value]$suffix)|;
911 print qq|${prefix
}$result->{name
}.$subtype\
[$value\
] == $values[$value]$suffix|;
923 print qq| printf("$test ... ok\\n");\n|;
927 print qq| printf("$test ... not ok\\n");\n|;
929 foreach my $result (@results)
931 my $type = $result->{type
};
932 my $subtype = $result->{subtype
};
933 my $suffix = $SubTypeSuffixes{$subtype};
934 my @values = @
{$result->{values}};
936 if ($type eq "eflags")
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|;
940 elsif ($type =~ /^fpu[cs]w$/)
942 print qq| printf(" $type & 0x%x = 0x%x (expected 0x%x)\\n", $values[0], $result->{name
}.uw\
[0\
] & $values[0], $values[1]);\n|;
946 foreach my $value (0 .. $#values)
948 print qq| printf(" $result->{name}.$subtype\[$value\] = $SubTypeFormats{$subtype} (expected $SubTypeFormats{$subtype})\\n", $result->{name
}.$subtype\
[$value\
], $values[$value]$suffix);\n|;
957 print qq| printf("$test ... ok\\n");\n|;
963 print qq| printf("$test ... failed\\n");\n|;
966 print qq| return;\n|;
971 print qq|int main
(int argc
, char
**argv
)\n|;
973 print qq| signal
(SIGILL
, handle_sigill
);\n|;
976 foreach my $test (@tests)
978 print qq| $test();\n|;
982 print qq| exit(0);\n|;