Commit e477b8b81ba5212747799ce71858e2b110fc6ae5
1 parent
b118d61e
correct eflags evaluation order for all operations - fixed important CPU state r…
…estoring bug in some exception cases - disabled unsafe inc flags optimisation git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@303 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
636 additions
and
339 deletions
Makefile
| ... | ... | @@ -174,7 +174,7 @@ op-$(TARGET_ARCH).o: op-$(TARGET_ARCH).c |
| 174 | 174 | helper-$(TARGET_ARCH).o: helper-$(TARGET_ARCH).c |
| 175 | 175 | $(CC) $(HELPER_CFLAGS) $(DEFINES) -c -o $@ $< |
| 176 | 176 | |
| 177 | -op-i386.o: op-i386.c opreg_template.h ops_template.h | |
| 177 | +op-i386.o: op-i386.c opreg_template.h ops_template.h ops_template_mem.h | |
| 178 | 178 | |
| 179 | 179 | op-arm.o: op-arm.c op-arm-template.h |
| 180 | 180 | ... | ... |
dyngen.c
| ... | ... | @@ -1200,11 +1200,11 @@ int load_elf(const char *filename, FILE *outfile, int out_type) |
| 1200 | 1200 | } |
| 1201 | 1201 | |
| 1202 | 1202 | if (out_type == OUT_INDEX_OP) { |
| 1203 | - fprintf(outfile, "DEF(nop1, 0, 0)\n"); | |
| 1204 | - fprintf(outfile, "DEF(nop2, 0, 0)\n"); | |
| 1205 | - fprintf(outfile, "DEF(nop3, 0, 0)\n"); | |
| 1206 | - fprintf(outfile, "DEF(nop, 0, 0)\n"); | |
| 1207 | 1203 | fprintf(outfile, "DEF(end, 0, 0)\n"); |
| 1204 | + fprintf(outfile, "DEF(nop, 0, 0)\n"); | |
| 1205 | + fprintf(outfile, "DEF(nop1, 1, 0)\n"); | |
| 1206 | + fprintf(outfile, "DEF(nop2, 2, 0)\n"); | |
| 1207 | + fprintf(outfile, "DEF(nop3, 3, 0)\n"); | |
| 1208 | 1208 | for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { |
| 1209 | 1209 | const char *name, *p; |
| 1210 | 1210 | name = strtab + sym->st_name; | ... | ... |
ops_template.h
| ... | ... | @@ -406,127 +406,6 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void) |
| 406 | 406 | |
| 407 | 407 | /* shifts */ |
| 408 | 408 | |
| 409 | -void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void) | |
| 410 | -{ | |
| 411 | - int count, src; | |
| 412 | - count = T1 & SHIFT_MASK; | |
| 413 | - if (count) { | |
| 414 | - CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C); | |
| 415 | - src = T0; | |
| 416 | - T0 &= DATA_MASK; | |
| 417 | - T0 = (T0 << count) | (T0 >> (DATA_BITS - count)); | |
| 418 | - CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | | |
| 419 | - (T0 & CC_C); | |
| 420 | - CC_OP = CC_OP_EFLAGS; | |
| 421 | - } | |
| 422 | - FORCE_RET(); | |
| 423 | -} | |
| 424 | - | |
| 425 | -void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1)(void) | |
| 426 | -{ | |
| 427 | - int count; | |
| 428 | - count = T1 & SHIFT_MASK; | |
| 429 | - if (count) { | |
| 430 | - T0 &= DATA_MASK; | |
| 431 | - T0 = (T0 << count) | (T0 >> (DATA_BITS - count)); | |
| 432 | - } | |
| 433 | - FORCE_RET(); | |
| 434 | -} | |
| 435 | - | |
| 436 | -void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void) | |
| 437 | -{ | |
| 438 | - int count, src; | |
| 439 | - count = T1 & SHIFT_MASK; | |
| 440 | - if (count) { | |
| 441 | - CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C); | |
| 442 | - src = T0; | |
| 443 | - T0 &= DATA_MASK; | |
| 444 | - T0 = (T0 >> count) | (T0 << (DATA_BITS - count)); | |
| 445 | - CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | | |
| 446 | - ((T0 >> (DATA_BITS - 1)) & CC_C); | |
| 447 | - CC_OP = CC_OP_EFLAGS; | |
| 448 | - } | |
| 449 | - FORCE_RET(); | |
| 450 | -} | |
| 451 | - | |
| 452 | -void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1)(void) | |
| 453 | -{ | |
| 454 | - int count; | |
| 455 | - count = T1 & SHIFT_MASK; | |
| 456 | - if (count) { | |
| 457 | - T0 &= DATA_MASK; | |
| 458 | - T0 = (T0 >> count) | (T0 << (DATA_BITS - count)); | |
| 459 | - } | |
| 460 | - FORCE_RET(); | |
| 461 | -} | |
| 462 | - | |
| 463 | -void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void) | |
| 464 | -{ | |
| 465 | - int count, res, eflags; | |
| 466 | - unsigned int src; | |
| 467 | - | |
| 468 | - count = T1 & 0x1f; | |
| 469 | -#if DATA_BITS == 16 | |
| 470 | - count = rclw_table[count]; | |
| 471 | -#elif DATA_BITS == 8 | |
| 472 | - count = rclb_table[count]; | |
| 473 | -#endif | |
| 474 | - if (count) { | |
| 475 | - eflags = cc_table[CC_OP].compute_all(); | |
| 476 | - T0 &= DATA_MASK; | |
| 477 | - src = T0; | |
| 478 | - res = (T0 << count) | ((eflags & CC_C) << (count - 1)); | |
| 479 | - if (count > 1) | |
| 480 | - res |= T0 >> (DATA_BITS + 1 - count); | |
| 481 | - T0 = res; | |
| 482 | - CC_SRC = (eflags & ~(CC_C | CC_O)) | | |
| 483 | - (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | | |
| 484 | - ((src >> (DATA_BITS - count)) & CC_C); | |
| 485 | - CC_OP = CC_OP_EFLAGS; | |
| 486 | - } | |
| 487 | - FORCE_RET(); | |
| 488 | -} | |
| 489 | - | |
| 490 | -void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void) | |
| 491 | -{ | |
| 492 | - int count, res, eflags; | |
| 493 | - unsigned int src; | |
| 494 | - | |
| 495 | - count = T1 & 0x1f; | |
| 496 | -#if DATA_BITS == 16 | |
| 497 | - count = rclw_table[count]; | |
| 498 | -#elif DATA_BITS == 8 | |
| 499 | - count = rclb_table[count]; | |
| 500 | -#endif | |
| 501 | - if (count) { | |
| 502 | - eflags = cc_table[CC_OP].compute_all(); | |
| 503 | - T0 &= DATA_MASK; | |
| 504 | - src = T0; | |
| 505 | - res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count)); | |
| 506 | - if (count > 1) | |
| 507 | - res |= T0 << (DATA_BITS + 1 - count); | |
| 508 | - T0 = res; | |
| 509 | - CC_SRC = (eflags & ~(CC_C | CC_O)) | | |
| 510 | - (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | | |
| 511 | - ((src >> (count - 1)) & CC_C); | |
| 512 | - CC_OP = CC_OP_EFLAGS; | |
| 513 | - } | |
| 514 | - FORCE_RET(); | |
| 515 | -} | |
| 516 | - | |
| 517 | -void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void) | |
| 518 | -{ | |
| 519 | - int count; | |
| 520 | - count = T1 & 0x1f; | |
| 521 | - if (count) { | |
| 522 | - CC_SRC = (DATA_TYPE)T0 << (count - 1); | |
| 523 | - T0 = T0 << count; | |
| 524 | - CC_DST = T0; | |
| 525 | - CC_OP = CC_OP_SHLB + SHIFT; | |
| 526 | - } | |
| 527 | - FORCE_RET(); | |
| 528 | -} | |
| 529 | - | |
| 530 | 409 | void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void) |
| 531 | 410 | { |
| 532 | 411 | int count; |
| ... | ... | @@ -535,20 +414,6 @@ void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void) |
| 535 | 414 | FORCE_RET(); |
| 536 | 415 | } |
| 537 | 416 | |
| 538 | -void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void) | |
| 539 | -{ | |
| 540 | - int count; | |
| 541 | - count = T1 & 0x1f; | |
| 542 | - if (count) { | |
| 543 | - T0 &= DATA_MASK; | |
| 544 | - CC_SRC = T0 >> (count - 1); | |
| 545 | - T0 = T0 >> count; | |
| 546 | - CC_DST = T0; | |
| 547 | - CC_OP = CC_OP_SARB + SHIFT; | |
| 548 | - } | |
| 549 | - FORCE_RET(); | |
| 550 | -} | |
| 551 | - | |
| 552 | 417 | void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void) |
| 553 | 418 | { |
| 554 | 419 | int count; |
| ... | ... | @@ -558,20 +423,6 @@ void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void) |
| 558 | 423 | FORCE_RET(); |
| 559 | 424 | } |
| 560 | 425 | |
| 561 | -void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void) | |
| 562 | -{ | |
| 563 | - int count, src; | |
| 564 | - count = T1 & 0x1f; | |
| 565 | - if (count) { | |
| 566 | - src = (DATA_STYPE)T0; | |
| 567 | - CC_SRC = src >> (count - 1); | |
| 568 | - T0 = src >> count; | |
| 569 | - CC_DST = T0; | |
| 570 | - CC_OP = CC_OP_SARB + SHIFT; | |
| 571 | - } | |
| 572 | - FORCE_RET(); | |
| 573 | -} | |
| 574 | - | |
| 575 | 426 | void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void) |
| 576 | 427 | { |
| 577 | 428 | int count, src; |
| ... | ... | @@ -581,162 +432,11 @@ void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void) |
| 581 | 432 | FORCE_RET(); |
| 582 | 433 | } |
| 583 | 434 | |
| 584 | -#if DATA_BITS == 16 | |
| 585 | -/* XXX: overflow flag might be incorrect in some cases in shldw */ | |
| 586 | -void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void) | |
| 587 | -{ | |
| 588 | - int count; | |
| 589 | - unsigned int res; | |
| 590 | - count = PARAM1; | |
| 591 | - T1 &= 0xffff; | |
| 592 | - res = T1 | (T0 << 16); | |
| 593 | - CC_SRC = res >> (32 - count); | |
| 594 | - res <<= count; | |
| 595 | - if (count > 16) | |
| 596 | - res |= T1 << (count - 16); | |
| 597 | - T0 = res >> 16; | |
| 598 | - CC_DST = T0; | |
| 599 | -} | |
| 600 | - | |
| 601 | -void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void) | |
| 602 | -{ | |
| 603 | - int count; | |
| 604 | - unsigned int res; | |
| 605 | - count = ECX & 0x1f; | |
| 606 | - if (count) { | |
| 607 | - T1 &= 0xffff; | |
| 608 | - res = T1 | (T0 << 16); | |
| 609 | - CC_SRC = res >> (32 - count); | |
| 610 | - res <<= count; | |
| 611 | - if (count > 16) | |
| 612 | - res |= T1 << (count - 16); | |
| 613 | - T0 = res >> 16; | |
| 614 | - CC_DST = T0; | |
| 615 | - CC_OP = CC_OP_SARB + SHIFT; | |
| 616 | - } | |
| 617 | - FORCE_RET(); | |
| 618 | -} | |
| 619 | - | |
| 620 | -void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void) | |
| 621 | -{ | |
| 622 | - int count; | |
| 623 | - unsigned int res; | |
| 624 | - | |
| 625 | - count = PARAM1; | |
| 626 | - res = (T0 & 0xffff) | (T1 << 16); | |
| 627 | - CC_SRC = res >> (count - 1); | |
| 628 | - res >>= count; | |
| 629 | - if (count > 16) | |
| 630 | - res |= T1 << (32 - count); | |
| 631 | - T0 = res; | |
| 632 | - CC_DST = T0; | |
| 633 | -} | |
| 634 | - | |
| 635 | - | |
| 636 | -void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void) | |
| 637 | -{ | |
| 638 | - int count; | |
| 639 | - unsigned int res; | |
| 640 | - | |
| 641 | - count = ECX & 0x1f; | |
| 642 | - if (count) { | |
| 643 | - res = (T0 & 0xffff) | (T1 << 16); | |
| 644 | - CC_SRC = res >> (count - 1); | |
| 645 | - res >>= count; | |
| 646 | - if (count > 16) | |
| 647 | - res |= T1 << (32 - count); | |
| 648 | - T0 = res; | |
| 649 | - CC_DST = T0; | |
| 650 | - CC_OP = CC_OP_SARB + SHIFT; | |
| 651 | - } | |
| 652 | - FORCE_RET(); | |
| 653 | -} | |
| 654 | -#endif | |
| 655 | - | |
| 656 | -#if DATA_BITS == 32 | |
| 657 | -void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void) | |
| 658 | -{ | |
| 659 | - int count; | |
| 660 | - count = PARAM1; | |
| 661 | - T0 &= DATA_MASK; | |
| 662 | - T1 &= DATA_MASK; | |
| 663 | - CC_SRC = T0 << (count - 1); | |
| 664 | - T0 = (T0 << count) | (T1 >> (DATA_BITS - count)); | |
| 665 | - CC_DST = T0; | |
| 666 | -} | |
| 667 | - | |
| 668 | -void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void) | |
| 669 | -{ | |
| 670 | - int count; | |
| 671 | - count = ECX & 0x1f; | |
| 672 | - if (count) { | |
| 673 | - T0 &= DATA_MASK; | |
| 674 | - T1 &= DATA_MASK; | |
| 675 | - CC_SRC = T0 << (count - 1); | |
| 676 | - T0 = (T0 << count) | (T1 >> (DATA_BITS - count)); | |
| 677 | - CC_DST = T0; | |
| 678 | - CC_OP = CC_OP_SHLB + SHIFT; | |
| 679 | - } | |
| 680 | - FORCE_RET(); | |
| 681 | -} | |
| 682 | - | |
| 683 | -void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void) | |
| 684 | -{ | |
| 685 | - int count; | |
| 686 | - count = PARAM1; | |
| 687 | - T0 &= DATA_MASK; | |
| 688 | - T1 &= DATA_MASK; | |
| 689 | - CC_SRC = T0 >> (count - 1); | |
| 690 | - T0 = (T0 >> count) | (T1 << (DATA_BITS - count)); | |
| 691 | - CC_DST = T0; | |
| 692 | -} | |
| 435 | +#undef MEM_WRITE | |
| 436 | +#include "ops_template_mem.h" | |
| 693 | 437 | |
| 694 | - | |
| 695 | -void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void) | |
| 696 | -{ | |
| 697 | - int count; | |
| 698 | - count = ECX & 0x1f; | |
| 699 | - if (count) { | |
| 700 | - T0 &= DATA_MASK; | |
| 701 | - T1 &= DATA_MASK; | |
| 702 | - CC_SRC = T0 >> (count - 1); | |
| 703 | - T0 = (T0 >> count) | (T1 << (DATA_BITS - count)); | |
| 704 | - CC_DST = T0; | |
| 705 | - CC_OP = CC_OP_SARB + SHIFT; | |
| 706 | - } | |
| 707 | - FORCE_RET(); | |
| 708 | -} | |
| 709 | -#endif | |
| 710 | - | |
| 711 | -/* carry add/sub (we only need to set CC_OP differently) */ | |
| 712 | - | |
| 713 | -void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void) | |
| 714 | -{ | |
| 715 | - int cf; | |
| 716 | - cf = cc_table[CC_OP].compute_c(); | |
| 717 | - T0 = T0 + T1 + cf; | |
| 718 | - CC_OP = CC_OP_ADDB + SHIFT + cf * 3; | |
| 719 | -} | |
| 720 | - | |
| 721 | -void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void) | |
| 722 | -{ | |
| 723 | - int cf; | |
| 724 | - cf = cc_table[CC_OP].compute_c(); | |
| 725 | - T0 = T0 - T1 - cf; | |
| 726 | - CC_OP = CC_OP_SUBB + SHIFT + cf * 3; | |
| 727 | -} | |
| 728 | - | |
| 729 | -void OPPROTO glue(glue(op_cmpxchg, SUFFIX), _T0_T1_EAX_cc)(void) | |
| 730 | -{ | |
| 731 | - CC_SRC = T0; | |
| 732 | - CC_DST = EAX - T0; | |
| 733 | - if ((DATA_TYPE)CC_DST == 0) { | |
| 734 | - T0 = T1; | |
| 735 | - } else { | |
| 736 | - EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK); | |
| 737 | - } | |
| 738 | - FORCE_RET(); | |
| 739 | -} | |
| 438 | +#define MEM_WRITE | |
| 439 | +#include "ops_template_mem.h" | |
| 740 | 440 | |
| 741 | 441 | /* bit operations */ |
| 742 | 442 | #if DATA_BITS >= 16 |
| ... | ... | @@ -752,7 +452,7 @@ void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void) |
| 752 | 452 | { |
| 753 | 453 | int count; |
| 754 | 454 | count = T1 & SHIFT_MASK; |
| 755 | - CC_SRC = T0 >> count; | |
| 455 | + T1 = T0 >> count; | |
| 756 | 456 | T0 |= (1 << count); |
| 757 | 457 | } |
| 758 | 458 | |
| ... | ... | @@ -760,7 +460,7 @@ void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void) |
| 760 | 460 | { |
| 761 | 461 | int count; |
| 762 | 462 | count = T1 & SHIFT_MASK; |
| 763 | - CC_SRC = T0 >> count; | |
| 463 | + T1 = T0 >> count; | |
| 764 | 464 | T0 &= ~(1 << count); |
| 765 | 465 | } |
| 766 | 466 | |
| ... | ... | @@ -768,7 +468,7 @@ void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void) |
| 768 | 468 | { |
| 769 | 469 | int count; |
| 770 | 470 | count = T1 & SHIFT_MASK; |
| 771 | - CC_SRC = T0 >> count; | |
| 471 | + T1 = T0 >> count; | |
| 772 | 472 | T0 ^= (1 << count); |
| 773 | 473 | } |
| 774 | 474 | |
| ... | ... | @@ -810,6 +510,13 @@ void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void) |
| 810 | 510 | |
| 811 | 511 | #endif |
| 812 | 512 | |
| 513 | +#if DATA_BITS == 32 | |
| 514 | +void OPPROTO op_update_bt_cc(void) | |
| 515 | +{ | |
| 516 | + CC_SRC = T1; | |
| 517 | +} | |
| 518 | +#endif | |
| 519 | + | |
| 813 | 520 | /* string operations */ |
| 814 | 521 | /* XXX: maybe use lower level instructions to ease 16 bit / segment handling */ |
| 815 | 522 | ... | ... |
ops_template_mem.h
0 → 100644
| 1 | +/* | |
| 2 | + * i386 micro operations (included several times to generate | |
| 3 | + * different operand sizes) | |
| 4 | + * | |
| 5 | + * Copyright (c) 2003 Fabrice Bellard | |
| 6 | + * | |
| 7 | + * This library is free software; you can redistribute it and/or | |
| 8 | + * modify it under the terms of the GNU Lesser General Public | |
| 9 | + * License as published by the Free Software Foundation; either | |
| 10 | + * version 2 of the License, or (at your option) any later version. | |
| 11 | + * | |
| 12 | + * This library is distributed in the hope that it will be useful, | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 | + * Lesser General Public License for more details. | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU Lesser General Public | |
| 18 | + * License along with this library; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | + */ | |
| 21 | +#ifdef MEM_WRITE | |
| 22 | + | |
| 23 | +#if DATA_BITS == 8 | |
| 24 | +#define MEM_SUFFIX b_mem | |
| 25 | +#elif DATA_BITS == 16 | |
| 26 | +#define MEM_SUFFIX w_mem | |
| 27 | +#elif DATA_BITS == 32 | |
| 28 | +#define MEM_SUFFIX l_mem | |
| 29 | +#endif | |
| 30 | + | |
| 31 | +#else | |
| 32 | + | |
| 33 | +#define MEM_SUFFIX SUFFIX | |
| 34 | + | |
| 35 | +#endif | |
| 36 | + | |
| 37 | +void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1_cc)(void) | |
| 38 | +{ | |
| 39 | + int count, src; | |
| 40 | + count = T1 & SHIFT_MASK; | |
| 41 | + if (count) { | |
| 42 | + src = T0; | |
| 43 | + T0 &= DATA_MASK; | |
| 44 | + T0 = (T0 << count) | (T0 >> (DATA_BITS - count)); | |
| 45 | +#ifdef MEM_WRITE | |
| 46 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 47 | +#endif | |
| 48 | + CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) | | |
| 49 | + (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | | |
| 50 | + (T0 & CC_C); | |
| 51 | + CC_OP = CC_OP_EFLAGS; | |
| 52 | + } | |
| 53 | + FORCE_RET(); | |
| 54 | +} | |
| 55 | + | |
| 56 | +void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1_cc)(void) | |
| 57 | +{ | |
| 58 | + int count, src; | |
| 59 | + count = T1 & SHIFT_MASK; | |
| 60 | + if (count) { | |
| 61 | + src = T0; | |
| 62 | + T0 &= DATA_MASK; | |
| 63 | + T0 = (T0 >> count) | (T0 << (DATA_BITS - count)); | |
| 64 | +#ifdef MEM_WRITE | |
| 65 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 66 | +#endif | |
| 67 | + CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) | | |
| 68 | + (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | | |
| 69 | + ((T0 >> (DATA_BITS - 1)) & CC_C); | |
| 70 | + CC_OP = CC_OP_EFLAGS; | |
| 71 | + } | |
| 72 | + FORCE_RET(); | |
| 73 | +} | |
| 74 | + | |
| 75 | +void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1)(void) | |
| 76 | +{ | |
| 77 | + int count; | |
| 78 | + count = T1 & SHIFT_MASK; | |
| 79 | + if (count) { | |
| 80 | + T0 &= DATA_MASK; | |
| 81 | + T0 = (T0 << count) | (T0 >> (DATA_BITS - count)); | |
| 82 | +#ifdef MEM_WRITE | |
| 83 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 84 | +#endif | |
| 85 | + } | |
| 86 | + FORCE_RET(); | |
| 87 | +} | |
| 88 | + | |
| 89 | +void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1)(void) | |
| 90 | +{ | |
| 91 | + int count; | |
| 92 | + count = T1 & SHIFT_MASK; | |
| 93 | + if (count) { | |
| 94 | + T0 &= DATA_MASK; | |
| 95 | + T0 = (T0 >> count) | (T0 << (DATA_BITS - count)); | |
| 96 | +#ifdef MEM_WRITE | |
| 97 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 98 | +#endif | |
| 99 | + } | |
| 100 | + FORCE_RET(); | |
| 101 | +} | |
| 102 | + | |
| 103 | +void OPPROTO glue(glue(op_rcl, MEM_SUFFIX), _T0_T1_cc)(void) | |
| 104 | +{ | |
| 105 | + int count, res, eflags; | |
| 106 | + unsigned int src; | |
| 107 | + | |
| 108 | + count = T1 & 0x1f; | |
| 109 | +#if DATA_BITS == 16 | |
| 110 | + count = rclw_table[count]; | |
| 111 | +#elif DATA_BITS == 8 | |
| 112 | + count = rclb_table[count]; | |
| 113 | +#endif | |
| 114 | + if (count) { | |
| 115 | + eflags = cc_table[CC_OP].compute_all(); | |
| 116 | + T0 &= DATA_MASK; | |
| 117 | + src = T0; | |
| 118 | + res = (T0 << count) | ((eflags & CC_C) << (count - 1)); | |
| 119 | + if (count > 1) | |
| 120 | + res |= T0 >> (DATA_BITS + 1 - count); | |
| 121 | + T0 = res; | |
| 122 | +#ifdef MEM_WRITE | |
| 123 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 124 | +#endif | |
| 125 | + CC_SRC = (eflags & ~(CC_C | CC_O)) | | |
| 126 | + (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | | |
| 127 | + ((src >> (DATA_BITS - count)) & CC_C); | |
| 128 | + CC_OP = CC_OP_EFLAGS; | |
| 129 | + } | |
| 130 | + FORCE_RET(); | |
| 131 | +} | |
| 132 | + | |
| 133 | +void OPPROTO glue(glue(op_rcr, MEM_SUFFIX), _T0_T1_cc)(void) | |
| 134 | +{ | |
| 135 | + int count, res, eflags; | |
| 136 | + unsigned int src; | |
| 137 | + | |
| 138 | + count = T1 & 0x1f; | |
| 139 | +#if DATA_BITS == 16 | |
| 140 | + count = rclw_table[count]; | |
| 141 | +#elif DATA_BITS == 8 | |
| 142 | + count = rclb_table[count]; | |
| 143 | +#endif | |
| 144 | + if (count) { | |
| 145 | + eflags = cc_table[CC_OP].compute_all(); | |
| 146 | + T0 &= DATA_MASK; | |
| 147 | + src = T0; | |
| 148 | + res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count)); | |
| 149 | + if (count > 1) | |
| 150 | + res |= T0 << (DATA_BITS + 1 - count); | |
| 151 | + T0 = res; | |
| 152 | +#ifdef MEM_WRITE | |
| 153 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 154 | +#endif | |
| 155 | + CC_SRC = (eflags & ~(CC_C | CC_O)) | | |
| 156 | + (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | | |
| 157 | + ((src >> (count - 1)) & CC_C); | |
| 158 | + CC_OP = CC_OP_EFLAGS; | |
| 159 | + } | |
| 160 | + FORCE_RET(); | |
| 161 | +} | |
| 162 | + | |
| 163 | +void OPPROTO glue(glue(op_shl, MEM_SUFFIX), _T0_T1_cc)(void) | |
| 164 | +{ | |
| 165 | + int count, src; | |
| 166 | + count = T1 & 0x1f; | |
| 167 | + if (count) { | |
| 168 | + src = (DATA_TYPE)T0 << (count - 1); | |
| 169 | + T0 = T0 << count; | |
| 170 | +#ifdef MEM_WRITE | |
| 171 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 172 | +#endif | |
| 173 | + CC_SRC = src; | |
| 174 | + CC_DST = T0; | |
| 175 | + CC_OP = CC_OP_SHLB + SHIFT; | |
| 176 | + } | |
| 177 | + FORCE_RET(); | |
| 178 | +} | |
| 179 | + | |
| 180 | +void OPPROTO glue(glue(op_shr, MEM_SUFFIX), _T0_T1_cc)(void) | |
| 181 | +{ | |
| 182 | + int count, src; | |
| 183 | + count = T1 & 0x1f; | |
| 184 | + if (count) { | |
| 185 | + T0 &= DATA_MASK; | |
| 186 | + src = T0 >> (count - 1); | |
| 187 | + T0 = T0 >> count; | |
| 188 | +#ifdef MEM_WRITE | |
| 189 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 190 | +#endif | |
| 191 | + CC_SRC = src; | |
| 192 | + CC_DST = T0; | |
| 193 | + CC_OP = CC_OP_SARB + SHIFT; | |
| 194 | + } | |
| 195 | + FORCE_RET(); | |
| 196 | +} | |
| 197 | + | |
| 198 | +void OPPROTO glue(glue(op_sar, MEM_SUFFIX), _T0_T1_cc)(void) | |
| 199 | +{ | |
| 200 | + int count, src; | |
| 201 | + count = T1 & 0x1f; | |
| 202 | + if (count) { | |
| 203 | + src = (DATA_STYPE)T0; | |
| 204 | + T0 = src >> count; | |
| 205 | + src = src >> (count - 1); | |
| 206 | +#ifdef MEM_WRITE | |
| 207 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 208 | +#endif | |
| 209 | + CC_SRC = src; | |
| 210 | + CC_DST = T0; | |
| 211 | + CC_OP = CC_OP_SARB + SHIFT; | |
| 212 | + } | |
| 213 | + FORCE_RET(); | |
| 214 | +} | |
| 215 | + | |
| 216 | +#if DATA_BITS == 16 | |
| 217 | +/* XXX: overflow flag might be incorrect in some cases in shldw */ | |
| 218 | +void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void) | |
| 219 | +{ | |
| 220 | + int count; | |
| 221 | + unsigned int res, tmp; | |
| 222 | + count = PARAM1; | |
| 223 | + T1 &= 0xffff; | |
| 224 | + res = T1 | (T0 << 16); | |
| 225 | + tmp = res >> (32 - count); | |
| 226 | + res <<= count; | |
| 227 | + if (count > 16) | |
| 228 | + res |= T1 << (count - 16); | |
| 229 | + T0 = res >> 16; | |
| 230 | +#ifdef MEM_WRITE | |
| 231 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 232 | +#endif | |
| 233 | + CC_SRC = tmp; | |
| 234 | + CC_DST = T0; | |
| 235 | +} | |
| 236 | + | |
| 237 | +void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void) | |
| 238 | +{ | |
| 239 | + int count; | |
| 240 | + unsigned int res, tmp; | |
| 241 | + count = ECX & 0x1f; | |
| 242 | + if (count) { | |
| 243 | + T1 &= 0xffff; | |
| 244 | + res = T1 | (T0 << 16); | |
| 245 | + tmp = res >> (32 - count); | |
| 246 | + res <<= count; | |
| 247 | + if (count > 16) | |
| 248 | + res |= T1 << (count - 16); | |
| 249 | + T0 = res >> 16; | |
| 250 | +#ifdef MEM_WRITE | |
| 251 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 252 | +#endif | |
| 253 | + CC_SRC = tmp; | |
| 254 | + CC_DST = T0; | |
| 255 | + CC_OP = CC_OP_SARB + SHIFT; | |
| 256 | + } | |
| 257 | + FORCE_RET(); | |
| 258 | +} | |
| 259 | + | |
| 260 | +void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void) | |
| 261 | +{ | |
| 262 | + int count; | |
| 263 | + unsigned int res, tmp; | |
| 264 | + | |
| 265 | + count = PARAM1; | |
| 266 | + res = (T0 & 0xffff) | (T1 << 16); | |
| 267 | + tmp = res >> (count - 1); | |
| 268 | + res >>= count; | |
| 269 | + if (count > 16) | |
| 270 | + res |= T1 << (32 - count); | |
| 271 | + T0 = res; | |
| 272 | +#ifdef MEM_WRITE | |
| 273 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 274 | +#endif | |
| 275 | + CC_SRC = tmp; | |
| 276 | + CC_DST = T0; | |
| 277 | +} | |
| 278 | + | |
| 279 | + | |
| 280 | +void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void) | |
| 281 | +{ | |
| 282 | + int count; | |
| 283 | + unsigned int res, tmp; | |
| 284 | + | |
| 285 | + count = ECX & 0x1f; | |
| 286 | + if (count) { | |
| 287 | + res = (T0 & 0xffff) | (T1 << 16); | |
| 288 | + tmp = res >> (count - 1); | |
| 289 | + res >>= count; | |
| 290 | + if (count > 16) | |
| 291 | + res |= T1 << (32 - count); | |
| 292 | + T0 = res; | |
| 293 | +#ifdef MEM_WRITE | |
| 294 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 295 | +#endif | |
| 296 | + CC_SRC = tmp; | |
| 297 | + CC_DST = T0; | |
| 298 | + CC_OP = CC_OP_SARB + SHIFT; | |
| 299 | + } | |
| 300 | + FORCE_RET(); | |
| 301 | +} | |
| 302 | +#endif | |
| 303 | + | |
| 304 | +#if DATA_BITS == 32 | |
| 305 | +void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void) | |
| 306 | +{ | |
| 307 | + int count, tmp; | |
| 308 | + count = PARAM1; | |
| 309 | + T0 &= DATA_MASK; | |
| 310 | + T1 &= DATA_MASK; | |
| 311 | + tmp = T0 << (count - 1); | |
| 312 | + T0 = (T0 << count) | (T1 >> (DATA_BITS - count)); | |
| 313 | +#ifdef MEM_WRITE | |
| 314 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 315 | +#endif | |
| 316 | + CC_SRC = tmp; | |
| 317 | + CC_DST = T0; | |
| 318 | +} | |
| 319 | + | |
| 320 | +void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void) | |
| 321 | +{ | |
| 322 | + int count, tmp; | |
| 323 | + count = ECX & 0x1f; | |
| 324 | + if (count) { | |
| 325 | + T0 &= DATA_MASK; | |
| 326 | + T1 &= DATA_MASK; | |
| 327 | + tmp = T0 << (count - 1); | |
| 328 | + T0 = (T0 << count) | (T1 >> (DATA_BITS - count)); | |
| 329 | +#ifdef MEM_WRITE | |
| 330 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 331 | +#endif | |
| 332 | + CC_SRC = tmp; | |
| 333 | + CC_DST = T0; | |
| 334 | + CC_OP = CC_OP_SHLB + SHIFT; | |
| 335 | + } | |
| 336 | + FORCE_RET(); | |
| 337 | +} | |
| 338 | + | |
| 339 | +void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void) | |
| 340 | +{ | |
| 341 | + int count, tmp; | |
| 342 | + count = PARAM1; | |
| 343 | + T0 &= DATA_MASK; | |
| 344 | + T1 &= DATA_MASK; | |
| 345 | + tmp = T0 >> (count - 1); | |
| 346 | + T0 = (T0 >> count) | (T1 << (DATA_BITS - count)); | |
| 347 | +#ifdef MEM_WRITE | |
| 348 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 349 | +#endif | |
| 350 | + CC_SRC = tmp; | |
| 351 | + CC_DST = T0; | |
| 352 | +} | |
| 353 | + | |
| 354 | + | |
| 355 | +void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void) | |
| 356 | +{ | |
| 357 | + int count, tmp; | |
| 358 | + count = ECX & 0x1f; | |
| 359 | + if (count) { | |
| 360 | + T0 &= DATA_MASK; | |
| 361 | + T1 &= DATA_MASK; | |
| 362 | + tmp = T0 >> (count - 1); | |
| 363 | + T0 = (T0 >> count) | (T1 << (DATA_BITS - count)); | |
| 364 | +#ifdef MEM_WRITE | |
| 365 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 366 | +#endif | |
| 367 | + CC_SRC = tmp; | |
| 368 | + CC_DST = T0; | |
| 369 | + CC_OP = CC_OP_SARB + SHIFT; | |
| 370 | + } | |
| 371 | + FORCE_RET(); | |
| 372 | +} | |
| 373 | +#endif | |
| 374 | + | |
| 375 | +/* carry add/sub (we only need to set CC_OP differently) */ | |
| 376 | + | |
| 377 | +void OPPROTO glue(glue(op_adc, MEM_SUFFIX), _T0_T1_cc)(void) | |
| 378 | +{ | |
| 379 | + int cf; | |
| 380 | + cf = cc_table[CC_OP].compute_c(); | |
| 381 | + T0 = T0 + T1 + cf; | |
| 382 | +#ifdef MEM_WRITE | |
| 383 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 384 | +#endif | |
| 385 | + CC_SRC = T1; | |
| 386 | + CC_DST = T0; | |
| 387 | + CC_OP = CC_OP_ADDB + SHIFT + cf * 3; | |
| 388 | +} | |
| 389 | + | |
| 390 | +void OPPROTO glue(glue(op_sbb, MEM_SUFFIX), _T0_T1_cc)(void) | |
| 391 | +{ | |
| 392 | + int cf; | |
| 393 | + cf = cc_table[CC_OP].compute_c(); | |
| 394 | + T0 = T0 - T1 - cf; | |
| 395 | +#ifdef MEM_WRITE | |
| 396 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 397 | +#endif | |
| 398 | + CC_SRC = T1; | |
| 399 | + CC_DST = T0; | |
| 400 | + CC_OP = CC_OP_SUBB + SHIFT + cf * 3; | |
| 401 | +} | |
| 402 | + | |
| 403 | +void OPPROTO glue(glue(op_cmpxchg, MEM_SUFFIX), _T0_T1_EAX_cc)(void) | |
| 404 | +{ | |
| 405 | + unsigned int src, dst; | |
| 406 | + | |
| 407 | + src = T0; | |
| 408 | + dst = EAX - T0; | |
| 409 | + if ((DATA_TYPE)dst == 0) { | |
| 410 | + T0 = T1; | |
| 411 | + } else { | |
| 412 | + EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK); | |
| 413 | + } | |
| 414 | +#ifdef MEM_WRITE | |
| 415 | + glue(st, SUFFIX)((uint8_t *)A0, T0); | |
| 416 | +#endif | |
| 417 | + CC_SRC = src; | |
| 418 | + CC_DST = dst; | |
| 419 | + FORCE_RET(); | |
| 420 | +} | |
| 421 | + | |
| 422 | +#undef MEM_SUFFIX | |
| 423 | +#undef MEM_WRITE | ... | ... |
translate-i386.c
| ... | ... | @@ -390,6 +390,21 @@ static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = { |
| 390 | 390 | }, |
| 391 | 391 | }; |
| 392 | 392 | |
| 393 | +static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3][2] = { | |
| 394 | + [OT_BYTE] = { | |
| 395 | + gen_op_adcb_mem_T0_T1_cc, | |
| 396 | + gen_op_sbbb_mem_T0_T1_cc, | |
| 397 | + }, | |
| 398 | + [OT_WORD] = { | |
| 399 | + gen_op_adcw_mem_T0_T1_cc, | |
| 400 | + gen_op_sbbw_mem_T0_T1_cc, | |
| 401 | + }, | |
| 402 | + [OT_LONG] = { | |
| 403 | + gen_op_adcl_mem_T0_T1_cc, | |
| 404 | + gen_op_sbbl_mem_T0_T1_cc, | |
| 405 | + }, | |
| 406 | +}; | |
| 407 | + | |
| 393 | 408 | static const int cc_op_arithb[8] = { |
| 394 | 409 | CC_OP_ADDB, |
| 395 | 410 | CC_OP_LOGICB, |
| ... | ... | @@ -407,6 +422,12 @@ static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = { |
| 407 | 422 | gen_op_cmpxchgl_T0_T1_EAX_cc, |
| 408 | 423 | }; |
| 409 | 424 | |
| 425 | +static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3] = { | |
| 426 | + gen_op_cmpxchgb_mem_T0_T1_EAX_cc, | |
| 427 | + gen_op_cmpxchgw_mem_T0_T1_EAX_cc, | |
| 428 | + gen_op_cmpxchgl_mem_T0_T1_EAX_cc, | |
| 429 | +}; | |
| 430 | + | |
| 410 | 431 | static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = { |
| 411 | 432 | [OT_BYTE] = { |
| 412 | 433 | gen_op_rolb_T0_T1_cc, |
| ... | ... | @@ -440,6 +461,39 @@ static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = { |
| 440 | 461 | }, |
| 441 | 462 | }; |
| 442 | 463 | |
| 464 | +static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3][8] = { | |
| 465 | + [OT_BYTE] = { | |
| 466 | + gen_op_rolb_mem_T0_T1_cc, | |
| 467 | + gen_op_rorb_mem_T0_T1_cc, | |
| 468 | + gen_op_rclb_mem_T0_T1_cc, | |
| 469 | + gen_op_rcrb_mem_T0_T1_cc, | |
| 470 | + gen_op_shlb_mem_T0_T1_cc, | |
| 471 | + gen_op_shrb_mem_T0_T1_cc, | |
| 472 | + gen_op_shlb_mem_T0_T1_cc, | |
| 473 | + gen_op_sarb_mem_T0_T1_cc, | |
| 474 | + }, | |
| 475 | + [OT_WORD] = { | |
| 476 | + gen_op_rolw_mem_T0_T1_cc, | |
| 477 | + gen_op_rorw_mem_T0_T1_cc, | |
| 478 | + gen_op_rclw_mem_T0_T1_cc, | |
| 479 | + gen_op_rcrw_mem_T0_T1_cc, | |
| 480 | + gen_op_shlw_mem_T0_T1_cc, | |
| 481 | + gen_op_shrw_mem_T0_T1_cc, | |
| 482 | + gen_op_shlw_mem_T0_T1_cc, | |
| 483 | + gen_op_sarw_mem_T0_T1_cc, | |
| 484 | + }, | |
| 485 | + [OT_LONG] = { | |
| 486 | + gen_op_roll_mem_T0_T1_cc, | |
| 487 | + gen_op_rorl_mem_T0_T1_cc, | |
| 488 | + gen_op_rcll_mem_T0_T1_cc, | |
| 489 | + gen_op_rcrl_mem_T0_T1_cc, | |
| 490 | + gen_op_shll_mem_T0_T1_cc, | |
| 491 | + gen_op_shrl_mem_T0_T1_cc, | |
| 492 | + gen_op_shll_mem_T0_T1_cc, | |
| 493 | + gen_op_sarl_mem_T0_T1_cc, | |
| 494 | + }, | |
| 495 | +}; | |
| 496 | + | |
| 443 | 497 | static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = { |
| 444 | 498 | [0] = { |
| 445 | 499 | gen_op_shldw_T0_T1_im_cc, |
| ... | ... | @@ -462,6 +516,28 @@ static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = { |
| 462 | 516 | }, |
| 463 | 517 | }; |
| 464 | 518 | |
| 519 | +static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[2][2] = { | |
| 520 | + [0] = { | |
| 521 | + gen_op_shldw_mem_T0_T1_im_cc, | |
| 522 | + gen_op_shrdw_mem_T0_T1_im_cc, | |
| 523 | + }, | |
| 524 | + [1] = { | |
| 525 | + gen_op_shldl_mem_T0_T1_im_cc, | |
| 526 | + gen_op_shrdl_mem_T0_T1_im_cc, | |
| 527 | + }, | |
| 528 | +}; | |
| 529 | + | |
| 530 | +static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[2][2] = { | |
| 531 | + [0] = { | |
| 532 | + gen_op_shldw_mem_T0_T1_ECX_cc, | |
| 533 | + gen_op_shrdw_mem_T0_T1_ECX_cc, | |
| 534 | + }, | |
| 535 | + [1] = { | |
| 536 | + gen_op_shldl_mem_T0_T1_ECX_cc, | |
| 537 | + gen_op_shrdl_mem_T0_T1_ECX_cc, | |
| 538 | + }, | |
| 539 | +}; | |
| 540 | + | |
| 465 | 541 | static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = { |
| 466 | 542 | [0] = { |
| 467 | 543 | gen_op_btw_T0_T1_cc, |
| ... | ... | @@ -763,11 +839,14 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) |
| 763 | 839 | case OP_SBBL: |
| 764 | 840 | if (s1->cc_op != CC_OP_DYNAMIC) |
| 765 | 841 | gen_op_set_cc_op(s1->cc_op); |
| 766 | - gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL](); | |
| 842 | + if (d != OR_TMP0) { | |
| 843 | + gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL](); | |
| 844 | + gen_op_mov_reg_T0[ot][d](); | |
| 845 | + } else { | |
| 846 | + gen_op_arithc_mem_T0_T1_cc[ot][op - OP_ADCL](); | |
| 847 | + } | |
| 767 | 848 | s1->cc_op = CC_OP_DYNAMIC; |
| 768 | - /* XXX: incorrect: CC_OP must also be modified AFTER memory access */ | |
| 769 | - gen_update_cc = gen_op_update2_cc; | |
| 770 | - break; | |
| 849 | + goto the_end; | |
| 771 | 850 | case OP_ADDL: |
| 772 | 851 | gen_op_addl_T0_T1(); |
| 773 | 852 | s1->cc_op = CC_OP_ADDB + ot; |
| ... | ... | @@ -802,6 +881,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) |
| 802 | 881 | exception support) */ |
| 803 | 882 | if (gen_update_cc) |
| 804 | 883 | gen_update_cc(); |
| 884 | + the_end: ; | |
| 805 | 885 | } |
| 806 | 886 | |
| 807 | 887 | /* if d == OR_TMP0, it means memory operand (address in A0) */ |
| ... | ... | @@ -831,14 +911,18 @@ static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) |
| 831 | 911 | { |
| 832 | 912 | if (d != OR_TMP0) |
| 833 | 913 | gen_op_mov_TN_reg[ot][0][d](); |
| 914 | + else | |
| 915 | + gen_op_ld_T0_A0[ot](); | |
| 834 | 916 | if (s != OR_TMP1) |
| 835 | 917 | gen_op_mov_TN_reg[ot][1][s](); |
| 836 | 918 | /* for zero counts, flags are not updated, so must do it dynamically */ |
| 837 | 919 | if (s1->cc_op != CC_OP_DYNAMIC) |
| 838 | 920 | gen_op_set_cc_op(s1->cc_op); |
| 839 | - | |
| 840 | - gen_op_shift_T0_T1_cc[ot][op](); | |
| 841 | - | |
| 921 | + | |
| 922 | + if (d != OR_TMP0) | |
| 923 | + gen_op_shift_T0_T1_cc[ot][op](); | |
| 924 | + else | |
| 925 | + gen_op_shift_mem_T0_T1_cc[ot][op](); | |
| 842 | 926 | if (d != OR_TMP0) |
| 843 | 927 | gen_op_mov_reg_T0[ot][d](); |
| 844 | 928 | s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
| ... | ... | @@ -1885,8 +1969,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
| 1885 | 1969 | } else { |
| 1886 | 1970 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 1887 | 1971 | gen_op_ld_T0_A0[ot](); |
| 1888 | - gen_op_cmpxchg_T0_T1_EAX_cc[ot](); | |
| 1889 | - gen_op_st_T0_A0[ot](); | |
| 1972 | + gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot](); | |
| 1890 | 1973 | } |
| 1891 | 1974 | s->cc_op = CC_OP_SUBB + ot; |
| 1892 | 1975 | break; |
| ... | ... | @@ -2264,7 +2347,6 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2264 | 2347 | |
| 2265 | 2348 | if (mod != 3) { |
| 2266 | 2349 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 2267 | - gen_op_ld_T0_A0[ot](); | |
| 2268 | 2350 | opreg = OR_TMP0; |
| 2269 | 2351 | } else { |
| 2270 | 2352 | opreg = rm + OR_EAX; |
| ... | ... | @@ -2279,10 +2361,6 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2279 | 2361 | } |
| 2280 | 2362 | gen_shifti(s, op, ot, opreg, shift); |
| 2281 | 2363 | } |
| 2282 | - | |
| 2283 | - if (mod != 3) { | |
| 2284 | - gen_op_st_T0_A0[ot](); | |
| 2285 | - } | |
| 2286 | 2364 | } |
| 2287 | 2365 | break; |
| 2288 | 2366 | case 0xd0: |
| ... | ... | @@ -2330,7 +2408,10 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2330 | 2408 | val = ldub(s->pc++); |
| 2331 | 2409 | val &= 0x1f; |
| 2332 | 2410 | if (val) { |
| 2333 | - gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val); | |
| 2411 | + if (mod == 3) | |
| 2412 | + gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val); | |
| 2413 | + else | |
| 2414 | + gen_op_shiftd_mem_T0_T1_im_cc[ot - OT_WORD][op](val); | |
| 2334 | 2415 | if (op == 0 && ot != OT_WORD) |
| 2335 | 2416 | s->cc_op = CC_OP_SHLB + ot; |
| 2336 | 2417 | else |
| ... | ... | @@ -2339,12 +2420,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2339 | 2420 | } else { |
| 2340 | 2421 | if (s->cc_op != CC_OP_DYNAMIC) |
| 2341 | 2422 | gen_op_set_cc_op(s->cc_op); |
| 2342 | - gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op](); | |
| 2423 | + if (mod == 3) | |
| 2424 | + gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op](); | |
| 2425 | + else | |
| 2426 | + gen_op_shiftd_mem_T0_T1_ECX_cc[ot - OT_WORD][op](); | |
| 2343 | 2427 | s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
| 2344 | 2428 | } |
| 2345 | - if (mod != 3) { | |
| 2346 | - gen_op_st_T0_A0[ot](); | |
| 2347 | - } else { | |
| 2429 | + if (mod == 3) { | |
| 2348 | 2430 | gen_op_mov_reg_T0[ot][rm](); |
| 2349 | 2431 | } |
| 2350 | 2432 | break; |
| ... | ... | @@ -3202,6 +3284,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3202 | 3284 | gen_op_st_T0_A0[ot](); |
| 3203 | 3285 | else |
| 3204 | 3286 | gen_op_mov_reg_T0[ot][rm](); |
| 3287 | + gen_op_update_bt_cc(); | |
| 3205 | 3288 | } |
| 3206 | 3289 | break; |
| 3207 | 3290 | case 0x1a3: /* bt Gv, Ev */ |
| ... | ... | @@ -3240,6 +3323,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3240 | 3323 | gen_op_st_T0_A0[ot](); |
| 3241 | 3324 | else |
| 3242 | 3325 | gen_op_mov_reg_T0[ot][rm](); |
| 3326 | + gen_op_update_bt_cc(); | |
| 3243 | 3327 | } |
| 3244 | 3328 | break; |
| 3245 | 3329 | case 0x1bc: /* bsf */ |
| ... | ... | @@ -3640,6 +3724,13 @@ static uint16_t opc_read_flags[NB_OPS] = { |
| 3640 | 3724 | [INDEX_op_sbbw_T0_T1_cc] = CC_C, |
| 3641 | 3725 | [INDEX_op_sbbl_T0_T1_cc] = CC_C, |
| 3642 | 3726 | |
| 3727 | + [INDEX_op_adcb_mem_T0_T1_cc] = CC_C, | |
| 3728 | + [INDEX_op_adcw_mem_T0_T1_cc] = CC_C, | |
| 3729 | + [INDEX_op_adcl_mem_T0_T1_cc] = CC_C, | |
| 3730 | + [INDEX_op_sbbb_mem_T0_T1_cc] = CC_C, | |
| 3731 | + [INDEX_op_sbbw_mem_T0_T1_cc] = CC_C, | |
| 3732 | + [INDEX_op_sbbl_mem_T0_T1_cc] = CC_C, | |
| 3733 | + | |
| 3643 | 3734 | /* subtle: due to the incl/decl implementation, C is used */ |
| 3644 | 3735 | [INDEX_op_update_inc_cc] = CC_C, |
| 3645 | 3736 | |
| ... | ... | @@ -3717,23 +3808,38 @@ static uint16_t opc_read_flags[NB_OPS] = { |
| 3717 | 3808 | [INDEX_op_rcrb_T0_T1_cc] = CC_C, |
| 3718 | 3809 | [INDEX_op_rcrw_T0_T1_cc] = CC_C, |
| 3719 | 3810 | [INDEX_op_rcrl_T0_T1_cc] = CC_C, |
| 3811 | + | |
| 3812 | + [INDEX_op_rclb_mem_T0_T1_cc] = CC_C, | |
| 3813 | + [INDEX_op_rclw_mem_T0_T1_cc] = CC_C, | |
| 3814 | + [INDEX_op_rcll_mem_T0_T1_cc] = CC_C, | |
| 3815 | + [INDEX_op_rcrb_mem_T0_T1_cc] = CC_C, | |
| 3816 | + [INDEX_op_rcrw_mem_T0_T1_cc] = CC_C, | |
| 3817 | + [INDEX_op_rcrl_mem_T0_T1_cc] = CC_C, | |
| 3720 | 3818 | }; |
| 3721 | 3819 | |
| 3722 | 3820 | /* flags written by an operation */ |
| 3723 | 3821 | static uint16_t opc_write_flags[NB_OPS] = { |
| 3724 | 3822 | [INDEX_op_update2_cc] = CC_OSZAPC, |
| 3725 | 3823 | [INDEX_op_update1_cc] = CC_OSZAPC, |
| 3824 | + [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC, | |
| 3825 | + [INDEX_op_update_neg_cc] = CC_OSZAPC, | |
| 3826 | + /* subtle: due to the incl/decl implementation, C is used */ | |
| 3827 | + [INDEX_op_update_inc_cc] = CC_OSZAPC, | |
| 3828 | + [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC, | |
| 3829 | + | |
| 3726 | 3830 | [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC, |
| 3727 | 3831 | [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC, |
| 3728 | 3832 | [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC, |
| 3729 | 3833 | [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC, |
| 3730 | 3834 | [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC, |
| 3731 | 3835 | [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC, |
| 3732 | - [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC, | |
| 3733 | - [INDEX_op_update_neg_cc] = CC_OSZAPC, | |
| 3734 | - /* subtle: due to the incl/decl implementation, C is used */ | |
| 3735 | - [INDEX_op_update_inc_cc] = CC_OSZAPC, | |
| 3736 | - [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC, | |
| 3836 | + | |
| 3837 | + [INDEX_op_adcb_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3838 | + [INDEX_op_adcw_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3839 | + [INDEX_op_adcl_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3840 | + [INDEX_op_sbbb_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3841 | + [INDEX_op_sbbw_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3842 | + [INDEX_op_sbbl_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3737 | 3843 | |
| 3738 | 3844 | [INDEX_op_mulb_AL_T0] = CC_OSZAPC, |
| 3739 | 3845 | [INDEX_op_imulb_AL_T0] = CC_OSZAPC, |
| ... | ... | @@ -3795,6 +3901,42 @@ static uint16_t opc_write_flags[NB_OPS] = { |
| 3795 | 3901 | [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC, |
| 3796 | 3902 | [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC, |
| 3797 | 3903 | |
| 3904 | + [INDEX_op_rolb_mem_T0_T1_cc] = CC_O | CC_C, | |
| 3905 | + [INDEX_op_rolw_mem_T0_T1_cc] = CC_O | CC_C, | |
| 3906 | + [INDEX_op_roll_mem_T0_T1_cc] = CC_O | CC_C, | |
| 3907 | + [INDEX_op_rorb_mem_T0_T1_cc] = CC_O | CC_C, | |
| 3908 | + [INDEX_op_rorw_mem_T0_T1_cc] = CC_O | CC_C, | |
| 3909 | + [INDEX_op_rorl_mem_T0_T1_cc] = CC_O | CC_C, | |
| 3910 | + | |
| 3911 | + [INDEX_op_rclb_mem_T0_T1_cc] = CC_O | CC_C, | |
| 3912 | + [INDEX_op_rclw_mem_T0_T1_cc] = CC_O | CC_C, | |
| 3913 | + [INDEX_op_rcll_mem_T0_T1_cc] = CC_O | CC_C, | |
| 3914 | + [INDEX_op_rcrb_mem_T0_T1_cc] = CC_O | CC_C, | |
| 3915 | + [INDEX_op_rcrw_mem_T0_T1_cc] = CC_O | CC_C, | |
| 3916 | + [INDEX_op_rcrl_mem_T0_T1_cc] = CC_O | CC_C, | |
| 3917 | + | |
| 3918 | + [INDEX_op_shlb_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3919 | + [INDEX_op_shlw_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3920 | + [INDEX_op_shll_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3921 | + | |
| 3922 | + [INDEX_op_shrb_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3923 | + [INDEX_op_shrw_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3924 | + [INDEX_op_shrl_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3925 | + | |
| 3926 | + [INDEX_op_sarb_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3927 | + [INDEX_op_sarw_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3928 | + [INDEX_op_sarl_mem_T0_T1_cc] = CC_OSZAPC, | |
| 3929 | + | |
| 3930 | + [INDEX_op_shldw_mem_T0_T1_ECX_cc] = CC_OSZAPC, | |
| 3931 | + [INDEX_op_shldl_mem_T0_T1_ECX_cc] = CC_OSZAPC, | |
| 3932 | + [INDEX_op_shldw_mem_T0_T1_im_cc] = CC_OSZAPC, | |
| 3933 | + [INDEX_op_shldl_mem_T0_T1_im_cc] = CC_OSZAPC, | |
| 3934 | + | |
| 3935 | + [INDEX_op_shrdw_mem_T0_T1_ECX_cc] = CC_OSZAPC, | |
| 3936 | + [INDEX_op_shrdl_mem_T0_T1_ECX_cc] = CC_OSZAPC, | |
| 3937 | + [INDEX_op_shrdw_mem_T0_T1_im_cc] = CC_OSZAPC, | |
| 3938 | + [INDEX_op_shrdl_mem_T0_T1_im_cc] = CC_OSZAPC, | |
| 3939 | + | |
| 3798 | 3940 | [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC, |
| 3799 | 3941 | [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC, |
| 3800 | 3942 | [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC, |
| ... | ... | @@ -3832,6 +3974,10 @@ static uint16_t opc_write_flags[NB_OPS] = { |
| 3832 | 3974 | [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC, |
| 3833 | 3975 | [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC, |
| 3834 | 3976 | |
| 3977 | + [INDEX_op_cmpxchgb_mem_T0_T1_EAX_cc] = CC_OSZAPC, | |
| 3978 | + [INDEX_op_cmpxchgw_mem_T0_T1_EAX_cc] = CC_OSZAPC, | |
| 3979 | + [INDEX_op_cmpxchgl_mem_T0_T1_EAX_cc] = CC_OSZAPC, | |
| 3980 | + | |
| 3835 | 3981 | [INDEX_op_cmpxchg8b] = CC_Z, |
| 3836 | 3982 | [INDEX_op_lar] = CC_Z, |
| 3837 | 3983 | [INDEX_op_lsl] = CC_Z, |
| ... | ... | @@ -3844,8 +3990,10 @@ static uint16_t opc_simpler[NB_OPS] = { |
| 3844 | 3990 | [INDEX_op_update2_cc] = INDEX_op_nop, |
| 3845 | 3991 | [INDEX_op_update1_cc] = INDEX_op_nop, |
| 3846 | 3992 | [INDEX_op_update_neg_cc] = INDEX_op_nop, |
| 3993 | +#if 0 | |
| 3994 | + /* broken: CC_OP logic must be rewritten */ | |
| 3847 | 3995 | [INDEX_op_update_inc_cc] = INDEX_op_nop, |
| 3848 | - | |
| 3996 | +#endif | |
| 3849 | 3997 | [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1, |
| 3850 | 3998 | [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1, |
| 3851 | 3999 | [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1, |
| ... | ... | @@ -3854,6 +4002,14 @@ static uint16_t opc_simpler[NB_OPS] = { |
| 3854 | 4002 | [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1, |
| 3855 | 4003 | [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1, |
| 3856 | 4004 | |
| 4005 | + [INDEX_op_rolb_mem_T0_T1_cc] = INDEX_op_rolb_mem_T0_T1, | |
| 4006 | + [INDEX_op_rolw_mem_T0_T1_cc] = INDEX_op_rolw_mem_T0_T1, | |
| 4007 | + [INDEX_op_roll_mem_T0_T1_cc] = INDEX_op_roll_mem_T0_T1, | |
| 4008 | + | |
| 4009 | + [INDEX_op_rorb_mem_T0_T1_cc] = INDEX_op_rorb_mem_T0_T1, | |
| 4010 | + [INDEX_op_rorw_mem_T0_T1_cc] = INDEX_op_rorw_mem_T0_T1, | |
| 4011 | + [INDEX_op_rorl_mem_T0_T1_cc] = INDEX_op_rorl_mem_T0_T1, | |
| 4012 | + | |
| 3857 | 4013 | [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1, |
| 3858 | 4014 | [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1, |
| 3859 | 4015 | [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1, |
| ... | ... | @@ -3971,6 +4127,10 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc |
| 3971 | 4127 | break; |
| 3972 | 4128 | } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && |
| 3973 | 4129 | (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32)); |
| 4130 | + if (!dc->tf && dc->is_jmp == DISAS_NEXT) { | |
| 4131 | + gen_jmp(dc, ret - (unsigned long)dc->cs_base); | |
| 4132 | + } | |
| 4133 | + | |
| 3974 | 4134 | /* we must store the eflags state if it is not already done */ |
| 3975 | 4135 | if (dc->is_jmp != DISAS_TB_JUMP) { |
| 3976 | 4136 | if (dc->cc_op != CC_OP_DYNAMIC) |
| ... | ... | @@ -3983,12 +4143,19 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc |
| 3983 | 4143 | if (dc->tf) { |
| 3984 | 4144 | gen_op_raise_exception(EXCP01_SSTP); |
| 3985 | 4145 | } |
| 3986 | - if (dc->is_jmp != 3) { | |
| 4146 | + if (dc->is_jmp != DISAS_TB_JUMP) { | |
| 3987 | 4147 | /* indicate that the hash table must be used to find the next TB */ |
| 3988 | 4148 | gen_op_movl_T0_0(); |
| 3989 | 4149 | } |
| 3990 | 4150 | *gen_opc_ptr = INDEX_op_end; |
| 3991 | - | |
| 4151 | + /* we don't forget to fill the last values */ | |
| 4152 | + if (search_pc) { | |
| 4153 | + j = gen_opc_ptr - gen_opc_buf; | |
| 4154 | + lj++; | |
| 4155 | + while (lj <= j) | |
| 4156 | + gen_opc_instr_start[lj++] = 0; | |
| 4157 | + } | |
| 4158 | + | |
| 3992 | 4159 | #ifdef DEBUG_DISAS |
| 3993 | 4160 | if (loglevel) { |
| 3994 | 4161 | fprintf(logfile, "----------------\n"); | ... | ... |