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