gen_insn_test.pl revision 9bea4c13fca0e3bb4b719dcb3ed63d47d479294e
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} =~ /^(m(8|16|32|64|128)|st|eflags|fpu[cs]w)$/) 632 { 633 $result->{argnum} = $argnum++; 634 } 635 } 636 637 foreach my $arg (@presets, @args) 638 { 639 if (defined($arg->{name})) 640 { 641 $arg->{argnum} = $argnum++; 642 } 643 } 644 645 foreach my $result (@results) 646 { 647 if ($result->{type} =~ /^(r(8|16|32|64)|mm|xmm)$/) 648 { 649 $result->{argnum} = $argnum++; 650 } 651 } 652 653 my $stateargnum = $argnum++; 654 655 print qq| char state\[108\];\n|; 656 print qq|\n|; 657 print qq| if (sigsetjmp(catchpoint, 1) == 0)\n|; 658 print qq| \{\n|; 659 print qq| asm\(\n|; 660# print qq| \"fsave %$stateargnum\\n\"\n|; 661 print qq| \"ffree %%st(7)\\n\"\n|; 662 print qq| \"ffree %%st(6)\\n\"\n|; 663 print qq| \"ffree %%st(5)\\n\"\n|; 664 print qq| \"ffree %%st(4)\\n\"\n|; 665 666 my @fpargs; 667 668 foreach my $arg (@presets, @args) 669 { 670 if ($arg->{type} eq "r8") 671 { 672 print qq| \"movb %$arg->{argnum}, %%$arg->{register}\\n\"\n|; 673 } 674 elsif ($arg->{type} eq "r16") 675 { 676 print qq| \"movw %$arg->{argnum}, %%$arg->{register}\\n\"\n|; 677 } 678 elsif ($arg->{type} eq "r32") 679 { 680 print qq| \"movl %$arg->{argnum}, %%$arg->{register}\\n\"\n|; 681 } 682 elsif ($arg->{type} eq "r64") 683 { 684 print qq| \"movq %$arg->{argnum}, %%$arg->{register}\\n\"\n|; 685 } 686 elsif ($arg->{type} eq "mm") 687 { 688 print qq| \"movq %$arg->{argnum}, %%$arg->{register}\\n\"\n|; 689 } 690 elsif ($arg->{type} eq "xmm") 691 { 692 print qq| \"movlps 0+%$arg->{argnum}, %%$arg->{register}\\n\"\n|; 693 print qq| \"movhps 8+%$arg->{argnum}, %%$arg->{register}\\n\"\n|; 694 } 695 elsif ($arg->{type} eq "st") 696 { 697 $fpargs[$RegNums{$arg->{register}}] = $arg; 698 } 699 } 700 701 foreach my $arg (reverse @fpargs) 702 { 703 if (defined($arg)) 704 { 705 if ($arg->{subtype} eq "ps") 706 { 707 print qq| \"flds %$arg->{argnum}\\n\"\n|; 708 } 709 elsif ($arg->{subtype} eq "pd") 710 { 711 print qq| \"fldl %$arg->{argnum}\\n\"\n|; 712 } 713 } 714 else 715 { 716 print qq| \"fldz\\n\"\n|; 717 } 718 } 719 720 if (defined($eflagsmask) || defined($eflagsset)) 721 { 722 print qq| \"pushfq\\n\"\n|; 723 print qq| \"andl \$$eflagsmask, (%%rsp)\\n\"\n| if defined($eflagsmask); 724 print qq| \"andl \$0, 4(%%rsp)\\n\"\n| if defined($eflagsmask); 725 print qq| \"orq \$$eflagsset, (%%rsp)\\n\"\n| if defined($eflagsset); 726 print qq| \"popfq\\n\"\n|; 727 } 728 729 if (defined($fpucwmask) || defined($fpucwset)) 730 { 731 print qq| \"subq \$2, %%rsp\\n\"\n|; 732 print qq| \"fstcw (%%rsp)\\n\"\n|; 733 print qq| \"andw \$$fpucwmask, (%%rsp)\\n\"\n| if defined($fpucwmask); 734 print qq| \"orw \$$fpucwset, (%%rsp)\\n\"\n| if defined($fpucwset); 735 print qq| \"fldcw (%%rsp)\\n\"\n|; 736 print qq| \"addq \$2, %%rsp\\n\"\n|; 737 } 738 739 print qq| \"$insn|; 740 741 my $prefix = " "; 742 743 foreach my $arg (@args) 744 { 745 next if $arg->{type} eq "eflags"; 746 747 if ($arg->{type} =~ /^(r8|r16|r32|r64|mm|xmm)$/) 748 { 749 print qq|$prefix%%$arg->{register}|; 750 } 751 elsif ($arg->{type} =~ /^st$/) 752 { 753 my $register = $arg->{register}; 754 755 $register =~ s/st(\d+)/st\($1\)/; 756 757 print qq|$prefix%%$register|; 758 } 759 elsif ($arg->{type} =~ /^(m(8|16|32|64|128))$/) 760 { 761 if (exists($arg->{result})) 762 { 763 print qq|$prefix%$arg->{result}->{argnum}|; 764 } 765 else 766 { 767 print qq|$prefix%$arg->{argnum}|; 768 } 769 } 770 elsif ($arg->{type} =~ /^imm(8|16|32|64)$/) 771 { 772 print qq|$prefix\$$arg->{value}|; 773 } 774 775 $prefix = ", "; 776 } 777 778 print qq|\\n\"\n|; 779 780 my @fpresults; 781 782 foreach my $result (@results) 783 { 784 if ($result->{type} eq "r8") 785 { 786 print qq| \"movb %%$result->{register}, %$result->{argnum}\\n\"\n|; 787 } 788 elsif ($result->{type} eq "r16") 789 { 790 print qq| \"movw %%$result->{register}, %$result->{argnum}\\n\"\n|; 791 } 792 elsif ($result->{type} eq "r32") 793 { 794 print qq| \"movl %%$result->{register}, %$result->{argnum}\\n\"\n|; 795 } 796 elsif ($result->{type} eq "r64") 797 { 798 print qq| \"movq %%$result->{register}, %$result->{argnum}\\n\"\n|; 799 } 800 elsif ($result->{type} eq "mm") 801 { 802 print qq| \"movq %%$result->{register}, %$result->{argnum}\\n\"\n|; 803 } 804 elsif ($result->{type} eq "xmm") 805 { 806 print qq| \"movlps %%$result->{register}, 0+%$result->{argnum}\\n\"\n|; 807 print qq| \"movhps %%$result->{register}, 8+%$result->{argnum}\\n\"\n|; 808 } 809 elsif ($result->{type} eq "st") 810 { 811 $fpresults[$RegNums{$result->{register}}] = $result; 812 } 813 elsif ($result->{type} eq "eflags") 814 { 815 print qq| \"pushfq\\n\"\n|; 816 print qq| \"popq %$result->{argnum}\\n\"\n|; 817 } 818 elsif ($result->{type} eq "fpucw") 819 { 820 print qq| \"fstcw %$result->{argnum}\\n\"\n|; 821 } 822 elsif ($result->{type} eq "fpusw") 823 { 824 print qq| \"fstsw %$result->{argnum}\\n\"\n|; 825 } 826 } 827 828 foreach my $result (@fpresults) 829 { 830 if (defined($result)) 831 { 832 if ($result->{subtype} eq "ps") 833 { 834 print qq| \"fstps %$result->{argnum}\\n\"\n|; 835 } 836 elsif ($result->{subtype} eq "pd") 837 { 838 print qq| \"fstpl %$result->{argnum}\\n\"\n|; 839 } 840 } 841 else 842 { 843 print qq| \"fincstp\\n\"\n|; 844 } 845 } 846 847# print qq| \"frstor %$stateargnum\\n\"\n|; 848 849 print qq| :|; 850 851 $prefix = " "; 852 853 foreach my $result (@results) 854 { 855 if ($result->{type} =~ /^(m(8|16|32|64|128)|st|eflags|fpu[cs]w)$/) 856 { 857 print qq|$prefix\"=m\" \($result->{name}\)|; 858 $prefix = ", "; 859 } 860 } 861 862 print qq|\n|; 863 864 $prefix = " : "; 865 866 foreach my $arg (@presets, @args) 867 { 868 if (defined($arg->{name})) 869 { 870 print qq|$prefix\"m\" \($arg->{name}\)|; 871 $prefix = ", "; 872 } 873 } 874 875 foreach my $result (@results) 876 { 877 if ($result->{type} =~ /^(r(8|16|32|64)|mm|xmm)$/) 878 { 879 print qq|$prefix\"m\" \($result->{name}\)|; 880 $prefix = ", "; 881 } 882 } 883 884 print qq|$prefix\"m\" \(state[0]\)\n|; 885 886 $prefix = " : "; 887 888 foreach my $arg (@presets, @args) 889 { 890 if ($arg->{register} && $arg->{type} ne "st") 891 { 892 my $register = $arg->{register}; 893 894 $register =~ s/^(r[0-9]+)[bwd]$/$1/; 895 print qq|$prefix\"$register\"|; 896 $prefix = ", "; 897 } 898 } 899 900 print qq|\n|; 901 902 print qq| \);\n|; 903 print qq|\n|; 904 905 if (@results) 906 { 907 print qq| if \(|; 908 909 $prefix = ""; 910 911 foreach my $result (@results) 912 { 913 my $type = $result->{type}; 914 my $subtype = $result->{subtype}; 915 my $suffix = $SubTypeSuffixes{$subtype}; 916 my @values = @{$result->{values}}; 917 918 if ($type eq "eflags") 919 { 920 print qq|${prefix}\($result->{name}.ud[0] & $values[0]UL\) == $values[1]UL|; 921 } 922 elsif ($type =~ /^fpu[cs]w$/) 923 { 924 print qq|${prefix}\($result->{name}.uw[0] & $values[0]\) == $values[1]|; 925 } 926 else 927 { 928 foreach my $value (0 .. $#values) 929 { 930 if ($subtype eq "ps") 931 { 932 print qq|${prefix}eq_float($result->{name}.$subtype\[$value\], $values[$value]$suffix)|; 933 } 934 elsif ($subtype eq "pd") 935 { 936 print qq|${prefix}eq_double($result->{name}.$subtype\[$value\], $values[$value]$suffix)|; 937 } 938 else 939 { 940 print qq|${prefix}$result->{name}.$subtype\[$value\] == $values[$value]$suffix|; 941 } 942 943 $prefix = " && "; 944 } 945 } 946 947 $prefix = " &&\n "; 948 } 949 950 print qq| \)\n|; 951 print qq| \{\n|; 952 print qq| printf("$test ... ok\\n");\n|; 953 print qq| \}\n|; 954 print qq| else\n|; 955 print qq| \{\n|; 956 print qq| printf("$test ... not ok\\n");\n|; 957 958 foreach my $result (@results) 959 { 960 my $type = $result->{type}; 961 my $subtype = $result->{subtype}; 962 my $suffix = $SubTypeSuffixes{$subtype}; 963 my @values = @{$result->{values}}; 964 965 if ($type eq "eflags") 966 { 967 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|; 968 } 969 elsif ($type =~ /^fpu[cs]w$/) 970 { 971 print qq| printf(" $type & 0x%x = 0x%x (expected 0x%x)\\n", $values[0], $result->{name}.uw\[0\] & $values[0], $values[1]);\n|; 972 } 973 else 974 { 975 foreach my $value (0 .. $#values) 976 { 977 print qq| printf(" $result->{name}.$subtype\[$value\] = $SubTypeFormats{$subtype} (expected $SubTypeFormats{$subtype})\\n", $result->{name}.$subtype\[$value\], $values[$value]$suffix);\n|; 978 } 979 } 980 } 981 982 print qq| \}\n|; 983 } 984 else 985 { 986 print qq| printf("$test ... ok\\n");\n|; 987 } 988 989 print qq| \}\n|; 990 print qq| else\n|; 991 print qq| \{\n|; 992 print qq| printf("$test ... failed\\n");\n|; 993 print qq| \}\n|; 994 print qq|\n|; 995 print qq| return;\n|; 996 print qq|\}\n|; 997 print qq|\n|; 998} 999 1000print qq|int main(int argc, char **argv)\n|; 1001print qq|\{\n|; 1002print qq| signal(SIGILL, handle_sigill);\n|; 1003print qq|\n|; 1004 1005foreach my $test (@tests) 1006{ 1007 print qq| $test();\n|; 1008} 1009 1010print qq|\n|; 1011print qq| exit(0);\n|; 1012print qq|\}\n|; 1013 1014exit 0; 1015