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