Commit 4021dab0594761c939b258cad67275c492b88e4d
1 parent
626df76a
soft mmu support - moved unrelated code to help2-i386.c - synthetize string instructions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@353 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
375 additions
and
415 deletions
translate-i386.c
| @@ -30,8 +30,6 @@ | @@ -30,8 +30,6 @@ | ||
| 30 | #include "exec.h" | 30 | #include "exec.h" |
| 31 | #include "disas.h" | 31 | #include "disas.h" |
| 32 | 32 | ||
| 33 | -//#define DEBUG_MMU | ||
| 34 | - | ||
| 35 | /* XXX: move that elsewhere */ | 33 | /* XXX: move that elsewhere */ |
| 36 | static uint16_t *gen_opc_ptr; | 34 | static uint16_t *gen_opc_ptr; |
| 37 | static uint32_t *gen_opparam_ptr; | 35 | static uint32_t *gen_opparam_ptr; |
| @@ -62,6 +60,7 @@ typedef struct DisasContext { | @@ -62,6 +60,7 @@ typedef struct DisasContext { | ||
| 62 | int cpl; | 60 | int cpl; |
| 63 | int iopl; | 61 | int iopl; |
| 64 | int tf; /* TF cpu flag */ | 62 | int tf; /* TF cpu flag */ |
| 63 | + int mem_index; /* select memory access functions */ | ||
| 65 | struct TranslationBlock *tb; | 64 | struct TranslationBlock *tb; |
| 66 | int popl_esp_hack; /* for correct popl with esp base handling */ | 65 | int popl_esp_hack; /* for correct popl with esp base handling */ |
| 67 | } DisasContext; | 66 | } DisasContext; |
| @@ -565,37 +564,81 @@ static GenOpFunc *gen_op_bsx_T0_cc[2][2] = { | @@ -565,37 +564,81 @@ static GenOpFunc *gen_op_bsx_T0_cc[2][2] = { | ||
| 565 | }, | 564 | }, |
| 566 | }; | 565 | }; |
| 567 | 566 | ||
| 568 | -static GenOpFunc *gen_op_lds_T0_A0[3] = { | 567 | +static GenOpFunc *gen_op_lds_T0_A0[3 * 3] = { |
| 569 | gen_op_ldsb_T0_A0, | 568 | gen_op_ldsb_T0_A0, |
| 570 | gen_op_ldsw_T0_A0, | 569 | gen_op_ldsw_T0_A0, |
| 570 | + NULL, | ||
| 571 | + | ||
| 572 | + gen_op_ldsb_kernel_T0_A0, | ||
| 573 | + gen_op_ldsw_kernel_T0_A0, | ||
| 574 | + NULL, | ||
| 575 | + | ||
| 576 | + gen_op_ldsb_user_T0_A0, | ||
| 577 | + gen_op_ldsw_user_T0_A0, | ||
| 578 | + NULL, | ||
| 571 | }; | 579 | }; |
| 572 | 580 | ||
| 573 | -static GenOpFunc *gen_op_ldu_T0_A0[3] = { | 581 | +static GenOpFunc *gen_op_ldu_T0_A0[3 * 3] = { |
| 574 | gen_op_ldub_T0_A0, | 582 | gen_op_ldub_T0_A0, |
| 575 | gen_op_lduw_T0_A0, | 583 | gen_op_lduw_T0_A0, |
| 584 | + NULL, | ||
| 585 | + | ||
| 586 | + gen_op_ldub_kernel_T0_A0, | ||
| 587 | + gen_op_lduw_kernel_T0_A0, | ||
| 588 | + NULL, | ||
| 589 | + | ||
| 590 | + gen_op_ldub_user_T0_A0, | ||
| 591 | + gen_op_lduw_user_T0_A0, | ||
| 592 | + NULL, | ||
| 576 | }; | 593 | }; |
| 577 | 594 | ||
| 578 | -/* sign does not matter */ | ||
| 579 | -static GenOpFunc *gen_op_ld_T0_A0[3] = { | 595 | +/* sign does not matter, except for lidt/lgdt call (TODO: fix it) */ |
| 596 | +static GenOpFunc *gen_op_ld_T0_A0[3 * 3] = { | ||
| 580 | gen_op_ldub_T0_A0, | 597 | gen_op_ldub_T0_A0, |
| 581 | gen_op_lduw_T0_A0, | 598 | gen_op_lduw_T0_A0, |
| 582 | gen_op_ldl_T0_A0, | 599 | gen_op_ldl_T0_A0, |
| 600 | + | ||
| 601 | + gen_op_ldub_kernel_T0_A0, | ||
| 602 | + gen_op_lduw_kernel_T0_A0, | ||
| 603 | + gen_op_ldl_kernel_T0_A0, | ||
| 604 | + | ||
| 605 | + gen_op_ldub_user_T0_A0, | ||
| 606 | + gen_op_lduw_user_T0_A0, | ||
| 607 | + gen_op_ldl_user_T0_A0, | ||
| 583 | }; | 608 | }; |
| 584 | 609 | ||
| 585 | -static GenOpFunc *gen_op_ld_T1_A0[3] = { | 610 | +static GenOpFunc *gen_op_ld_T1_A0[3 * 3] = { |
| 586 | gen_op_ldub_T1_A0, | 611 | gen_op_ldub_T1_A0, |
| 587 | gen_op_lduw_T1_A0, | 612 | gen_op_lduw_T1_A0, |
| 588 | gen_op_ldl_T1_A0, | 613 | gen_op_ldl_T1_A0, |
| 614 | + | ||
| 615 | + gen_op_ldub_kernel_T1_A0, | ||
| 616 | + gen_op_lduw_kernel_T1_A0, | ||
| 617 | + gen_op_ldl_kernel_T1_A0, | ||
| 618 | + | ||
| 619 | + gen_op_ldub_user_T1_A0, | ||
| 620 | + gen_op_lduw_user_T1_A0, | ||
| 621 | + gen_op_ldl_user_T1_A0, | ||
| 589 | }; | 622 | }; |
| 590 | 623 | ||
| 591 | -static GenOpFunc *gen_op_st_T0_A0[3] = { | 624 | +static GenOpFunc *gen_op_st_T0_A0[3 * 3] = { |
| 592 | gen_op_stb_T0_A0, | 625 | gen_op_stb_T0_A0, |
| 593 | gen_op_stw_T0_A0, | 626 | gen_op_stw_T0_A0, |
| 594 | gen_op_stl_T0_A0, | 627 | gen_op_stl_T0_A0, |
| 628 | + | ||
| 629 | + gen_op_stb_kernel_T0_A0, | ||
| 630 | + gen_op_stw_kernel_T0_A0, | ||
| 631 | + gen_op_stl_kernel_T0_A0, | ||
| 632 | + | ||
| 633 | + gen_op_stb_user_T0_A0, | ||
| 634 | + gen_op_stw_user_T0_A0, | ||
| 635 | + gen_op_stl_user_T0_A0, | ||
| 595 | }; | 636 | }; |
| 596 | 637 | ||
| 597 | /* the _a32 and _a16 string operations use A0 as the base register. */ | 638 | /* the _a32 and _a16 string operations use A0 as the base register. */ |
| 598 | 639 | ||
| 640 | +#define STRINGOP_NB 9 | ||
| 641 | + | ||
| 599 | #define STRINGOP(x) \ | 642 | #define STRINGOP(x) \ |
| 600 | gen_op_ ## x ## b_fast, \ | 643 | gen_op_ ## x ## b_fast, \ |
| 601 | gen_op_ ## x ## w_fast, \ | 644 | gen_op_ ## x ## w_fast, \ |
| @@ -607,44 +650,275 @@ static GenOpFunc *gen_op_st_T0_A0[3] = { | @@ -607,44 +650,275 @@ static GenOpFunc *gen_op_st_T0_A0[3] = { | ||
| 607 | gen_op_ ## x ## w_a16, \ | 650 | gen_op_ ## x ## w_a16, \ |
| 608 | gen_op_ ## x ## l_a16, | 651 | gen_op_ ## x ## l_a16, |
| 609 | 652 | ||
| 610 | -static GenOpFunc *gen_op_movs[9 * 2] = { | ||
| 611 | - STRINGOP(movs) | ||
| 612 | - STRINGOP(rep_movs) | 653 | +static GenOpFunc *gen_op_scas[STRINGOP_NB * 3] = { |
| 654 | + STRINGOP(repz_scas) | ||
| 655 | + STRINGOP(repnz_scas) | ||
| 613 | }; | 656 | }; |
| 614 | 657 | ||
| 615 | -static GenOpFunc *gen_op_stos[9 * 2] = { | ||
| 616 | - STRINGOP(stos) | ||
| 617 | - STRINGOP(rep_stos) | 658 | +static GenOpFunc *gen_op_cmps[STRINGOP_NB * 3] = { |
| 659 | + STRINGOP(repz_cmps) | ||
| 660 | + STRINGOP(repnz_cmps) | ||
| 618 | }; | 661 | }; |
| 619 | 662 | ||
| 620 | -static GenOpFunc *gen_op_lods[9 * 2] = { | ||
| 621 | - STRINGOP(lods) | ||
| 622 | - STRINGOP(rep_lods) | ||
| 623 | -}; | 663 | +static inline void gen_string_movl_A0_ESI(DisasContext *s) |
| 664 | +{ | ||
| 665 | + int override; | ||
| 624 | 666 | ||
| 625 | -static GenOpFunc *gen_op_scas[9 * 3] = { | ||
| 626 | - STRINGOP(scas) | ||
| 627 | - STRINGOP(repz_scas) | ||
| 628 | - STRINGOP(repnz_scas) | 667 | + override = s->override; |
| 668 | + if (s->aflag) { | ||
| 669 | + /* 32 bit address */ | ||
| 670 | + if (s->addseg && override < 0) | ||
| 671 | + override = R_DS; | ||
| 672 | + if (override >= 0) { | ||
| 673 | + gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base)); | ||
| 674 | + gen_op_addl_A0_reg_sN[0][R_ESI](); | ||
| 675 | + } else { | ||
| 676 | + gen_op_movl_A0_reg[R_ESI](); | ||
| 677 | + } | ||
| 678 | + } else { | ||
| 679 | + /* 16 address, always override */ | ||
| 680 | + if (override < 0) | ||
| 681 | + override = R_DS; | ||
| 682 | + gen_op_movl_A0_reg[R_ESI](); | ||
| 683 | + gen_op_andl_A0_ffff(); | ||
| 684 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); | ||
| 685 | + } | ||
| 686 | +} | ||
| 687 | + | ||
| 688 | +static inline void gen_string_movl_A0_EDI(DisasContext *s) | ||
| 689 | +{ | ||
| 690 | + if (s->aflag) { | ||
| 691 | + if (s->addseg) { | ||
| 692 | + gen_op_movl_A0_seg(offsetof(CPUX86State,segs[R_ES].base)); | ||
| 693 | + gen_op_addl_A0_reg_sN[0][R_EDI](); | ||
| 694 | + } else { | ||
| 695 | + gen_op_movl_A0_reg[R_EDI](); | ||
| 696 | + } | ||
| 697 | + } else { | ||
| 698 | + gen_op_movl_A0_reg[R_EDI](); | ||
| 699 | + gen_op_andl_A0_ffff(); | ||
| 700 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_ES].base)); | ||
| 701 | + } | ||
| 702 | +} | ||
| 703 | + | ||
| 704 | +static GenOpFunc *gen_op_movl_T0_Dshift[3] = { | ||
| 705 | + gen_op_movl_T0_Dshiftb, | ||
| 706 | + gen_op_movl_T0_Dshiftw, | ||
| 707 | + gen_op_movl_T0_Dshiftl, | ||
| 629 | }; | 708 | }; |
| 630 | 709 | ||
| 631 | -static GenOpFunc *gen_op_cmps[9 * 3] = { | ||
| 632 | - STRINGOP(cmps) | ||
| 633 | - STRINGOP(repz_cmps) | ||
| 634 | - STRINGOP(repnz_cmps) | 710 | +static GenOpFunc2 *gen_op_jz_ecx[2] = { |
| 711 | + gen_op_jz_ecxw, | ||
| 712 | + gen_op_jz_ecxl, | ||
| 713 | +}; | ||
| 714 | + | ||
| 715 | +static GenOpFunc *gen_op_dec_ECX[2] = { | ||
| 716 | + gen_op_decw_ECX, | ||
| 717 | + gen_op_decl_ECX, | ||
| 635 | }; | 718 | }; |
| 636 | 719 | ||
| 637 | -static GenOpFunc *gen_op_ins[9 * 2] = { | ||
| 638 | - STRINGOP(ins) | ||
| 639 | - STRINGOP(rep_ins) | 720 | +static GenOpFunc2 *gen_op_string_jnz_sub[2][3] = { |
| 721 | + { | ||
| 722 | + gen_op_string_jnz_subb, | ||
| 723 | + gen_op_string_jnz_subw, | ||
| 724 | + gen_op_string_jnz_subl, | ||
| 725 | + }, | ||
| 726 | + { | ||
| 727 | + gen_op_string_jz_subb, | ||
| 728 | + gen_op_string_jz_subw, | ||
| 729 | + gen_op_string_jz_subl, | ||
| 730 | + }, | ||
| 640 | }; | 731 | }; |
| 641 | 732 | ||
| 733 | +static GenOpFunc *gen_op_in_DX_T0[3] = { | ||
| 734 | + gen_op_inb_DX_T0, | ||
| 735 | + gen_op_inw_DX_T0, | ||
| 736 | + gen_op_inl_DX_T0, | ||
| 737 | +}; | ||
| 642 | 738 | ||
| 643 | -static GenOpFunc *gen_op_outs[9 * 2] = { | ||
| 644 | - STRINGOP(outs) | ||
| 645 | - STRINGOP(rep_outs) | 739 | +static GenOpFunc *gen_op_out_DX_T0[3] = { |
| 740 | + gen_op_outb_DX_T0, | ||
| 741 | + gen_op_outw_DX_T0, | ||
| 742 | + gen_op_outl_DX_T0, | ||
| 646 | }; | 743 | }; |
| 647 | 744 | ||
| 745 | +static inline void gen_movs(DisasContext *s, int ot) | ||
| 746 | +{ | ||
| 747 | + gen_string_movl_A0_ESI(s); | ||
| 748 | + gen_op_ld_T0_A0[ot + s->mem_index](); | ||
| 749 | + gen_string_movl_A0_EDI(s); | ||
| 750 | + gen_op_st_T0_A0[ot + s->mem_index](); | ||
| 751 | + gen_op_movl_T0_Dshift[ot](); | ||
| 752 | + if (s->aflag) { | ||
| 753 | + gen_op_addl_ESI_T0(); | ||
| 754 | + gen_op_addl_EDI_T0(); | ||
| 755 | + } else { | ||
| 756 | + gen_op_addw_ESI_T0(); | ||
| 757 | + gen_op_addw_EDI_T0(); | ||
| 758 | + } | ||
| 759 | +} | ||
| 760 | + | ||
| 761 | +/* same method as Valgrind : we generate jumps to current or next | ||
| 762 | + instruction */ | ||
| 763 | +static inline void gen_repz_movs(DisasContext *s, int ot, | ||
| 764 | + unsigned int cur_eip, unsigned int next_eip) | ||
| 765 | +{ | ||
| 766 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 767 | + gen_op_set_cc_op(s->cc_op); | ||
| 768 | + gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip); | ||
| 769 | + gen_movs(s, ot); | ||
| 770 | + gen_op_dec_ECX[s->aflag](); | ||
| 771 | + gen_op_jmp_tb_next((long)s->tb, cur_eip); | ||
| 772 | + s->is_jmp = 3; | ||
| 773 | +} | ||
| 774 | + | ||
| 775 | +static inline void gen_stos(DisasContext *s, int ot) | ||
| 776 | +{ | ||
| 777 | + gen_op_mov_TN_reg[OT_LONG][0][R_EAX](); | ||
| 778 | + gen_string_movl_A0_EDI(s); | ||
| 779 | + gen_op_st_T0_A0[ot + s->mem_index](); | ||
| 780 | + gen_op_movl_T0_Dshift[ot](); | ||
| 781 | + if (s->aflag) { | ||
| 782 | + gen_op_addl_EDI_T0(); | ||
| 783 | + } else { | ||
| 784 | + gen_op_addw_EDI_T0(); | ||
| 785 | + } | ||
| 786 | +} | ||
| 787 | + | ||
| 788 | +static inline void gen_repz_stos(DisasContext *s, int ot, | ||
| 789 | + unsigned int cur_eip, unsigned int next_eip) | ||
| 790 | +{ | ||
| 791 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 792 | + gen_op_set_cc_op(s->cc_op); | ||
| 793 | + gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip); | ||
| 794 | + gen_stos(s, ot); | ||
| 795 | + gen_op_dec_ECX[s->aflag](); | ||
| 796 | + gen_op_jmp_tb_next((long)s->tb, cur_eip); | ||
| 797 | + s->is_jmp = 3; | ||
| 798 | +} | ||
| 799 | + | ||
| 800 | +static inline void gen_lods(DisasContext *s, int ot) | ||
| 801 | +{ | ||
| 802 | + gen_string_movl_A0_ESI(s); | ||
| 803 | + gen_op_ld_T0_A0[ot + s->mem_index](); | ||
| 804 | + gen_op_mov_reg_T0[ot][R_EAX](); | ||
| 805 | + gen_op_movl_T0_Dshift[ot](); | ||
| 806 | + if (s->aflag) { | ||
| 807 | + gen_op_addl_ESI_T0(); | ||
| 808 | + } else { | ||
| 809 | + gen_op_addw_ESI_T0(); | ||
| 810 | + } | ||
| 811 | +} | ||
| 812 | + | ||
| 813 | +static inline void gen_repz_lods(DisasContext *s, int ot, | ||
| 814 | + unsigned int cur_eip, unsigned int next_eip) | ||
| 815 | +{ | ||
| 816 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 817 | + gen_op_set_cc_op(s->cc_op); | ||
| 818 | + gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip); | ||
| 819 | + gen_lods(s, ot); | ||
| 820 | + gen_op_dec_ECX[s->aflag](); | ||
| 821 | + gen_op_jmp_tb_next((long)s->tb, cur_eip); | ||
| 822 | + s->is_jmp = 3; | ||
| 823 | +} | ||
| 824 | + | ||
| 825 | +static inline void gen_scas(DisasContext *s, int ot) | ||
| 826 | +{ | ||
| 827 | + gen_op_mov_TN_reg[OT_LONG][0][R_EAX](); | ||
| 828 | + gen_string_movl_A0_EDI(s); | ||
| 829 | + gen_op_ld_T1_A0[ot + s->mem_index](); | ||
| 830 | + gen_op_cmpl_T0_T1_cc(); | ||
| 831 | + gen_op_movl_T0_Dshift[ot](); | ||
| 832 | + if (s->aflag) { | ||
| 833 | + gen_op_addl_EDI_T0(); | ||
| 834 | + } else { | ||
| 835 | + gen_op_addw_EDI_T0(); | ||
| 836 | + } | ||
| 837 | +} | ||
| 838 | + | ||
| 839 | +#if 0 | ||
| 840 | +static inline void gen_repz_scas(DisasContext *s, int ot, | ||
| 841 | + unsigned int cur_eip, unsigned int next_eip, | ||
| 842 | + int nz) | ||
| 843 | +{ | ||
| 844 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 845 | + gen_op_set_cc_op(s->cc_op); | ||
| 846 | + gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip); | ||
| 847 | + gen_scas(s, ot); | ||
| 848 | + gen_op_set_cc_op(CC_OP_SUBB + ot); | ||
| 849 | + gen_op_string_jnz_sub[nz][ot]((long)s->tb, next_eip); | ||
| 850 | + gen_op_dec_ECX[s->aflag](); | ||
| 851 | + gen_op_jmp_tb_next((long)s->tb, cur_eip); | ||
| 852 | + s->is_jmp = 3; | ||
| 853 | +} | ||
| 854 | +#endif | ||
| 855 | + | ||
| 856 | +static inline void gen_cmps(DisasContext *s, int ot) | ||
| 857 | +{ | ||
| 858 | + gen_string_movl_A0_ESI(s); | ||
| 859 | + gen_op_ld_T0_A0[ot + s->mem_index](); | ||
| 860 | + gen_string_movl_A0_EDI(s); | ||
| 861 | + gen_op_ld_T1_A0[ot + s->mem_index](); | ||
| 862 | + gen_op_cmpl_T0_T1_cc(); | ||
| 863 | + gen_op_movl_T0_Dshift[ot](); | ||
| 864 | + if (s->aflag) { | ||
| 865 | + gen_op_addl_ESI_T0(); | ||
| 866 | + gen_op_addl_EDI_T0(); | ||
| 867 | + } else { | ||
| 868 | + gen_op_addw_ESI_T0(); | ||
| 869 | + gen_op_addw_EDI_T0(); | ||
| 870 | + } | ||
| 871 | +} | ||
| 872 | + | ||
| 873 | +static inline void gen_ins(DisasContext *s, int ot) | ||
| 874 | +{ | ||
| 875 | + gen_op_in_DX_T0[ot](); | ||
| 876 | + gen_string_movl_A0_EDI(s); | ||
| 877 | + gen_op_st_T0_A0[ot + s->mem_index](); | ||
| 878 | + gen_op_movl_T0_Dshift[ot](); | ||
| 879 | + if (s->aflag) { | ||
| 880 | + gen_op_addl_EDI_T0(); | ||
| 881 | + } else { | ||
| 882 | + gen_op_addw_EDI_T0(); | ||
| 883 | + } | ||
| 884 | +} | ||
| 885 | + | ||
| 886 | +static inline void gen_repz_ins(DisasContext *s, int ot, | ||
| 887 | + unsigned int cur_eip, unsigned int next_eip) | ||
| 888 | +{ | ||
| 889 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 890 | + gen_op_set_cc_op(s->cc_op); | ||
| 891 | + gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip); | ||
| 892 | + gen_ins(s, ot); | ||
| 893 | + gen_op_dec_ECX[s->aflag](); | ||
| 894 | + gen_op_jmp_tb_next((long)s->tb, cur_eip); | ||
| 895 | + s->is_jmp = 3; | ||
| 896 | +} | ||
| 897 | + | ||
| 898 | +static inline void gen_outs(DisasContext *s, int ot) | ||
| 899 | +{ | ||
| 900 | + gen_string_movl_A0_ESI(s); | ||
| 901 | + gen_op_ld_T0_A0[ot + s->mem_index](); | ||
| 902 | + gen_op_out_DX_T0[ot](); | ||
| 903 | + gen_op_movl_T0_Dshift[ot](); | ||
| 904 | + if (s->aflag) { | ||
| 905 | + gen_op_addl_ESI_T0(); | ||
| 906 | + } else { | ||
| 907 | + gen_op_addw_ESI_T0(); | ||
| 908 | + } | ||
| 909 | +} | ||
| 910 | + | ||
| 911 | +static inline void gen_repz_outs(DisasContext *s, int ot, | ||
| 912 | + unsigned int cur_eip, unsigned int next_eip) | ||
| 913 | +{ | ||
| 914 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 915 | + gen_op_set_cc_op(s->cc_op); | ||
| 916 | + gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip); | ||
| 917 | + gen_outs(s, ot); | ||
| 918 | + gen_op_dec_ECX[s->aflag](); | ||
| 919 | + gen_op_jmp_tb_next((long)s->tb, cur_eip); | ||
| 920 | + s->is_jmp = 3; | ||
| 921 | +} | ||
| 648 | 922 | ||
| 649 | static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func) | 923 | static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func) |
| 650 | { | 924 | { |
| @@ -833,7 +1107,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) | @@ -833,7 +1107,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) | ||
| 833 | if (d != OR_TMP0) { | 1107 | if (d != OR_TMP0) { |
| 834 | gen_op_mov_TN_reg[ot][0][d](); | 1108 | gen_op_mov_TN_reg[ot][0][d](); |
| 835 | } else { | 1109 | } else { |
| 836 | - gen_op_ld_T0_A0[ot](); | 1110 | + gen_op_ld_T0_A0[ot + s1->mem_index](); |
| 837 | } | 1111 | } |
| 838 | switch(op) { | 1112 | switch(op) { |
| 839 | case OP_ADCL: | 1113 | case OP_ADCL: |
| @@ -876,7 +1150,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) | @@ -876,7 +1150,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) | ||
| 876 | if (d != OR_TMP0) | 1150 | if (d != OR_TMP0) |
| 877 | gen_op_mov_reg_T0[ot][d](); | 1151 | gen_op_mov_reg_T0[ot][d](); |
| 878 | else | 1152 | else |
| 879 | - gen_op_st_T0_A0[ot](); | 1153 | + gen_op_st_T0_A0[ot + s1->mem_index](); |
| 880 | } | 1154 | } |
| 881 | /* the flags update must happen after the memory write (precise | 1155 | /* the flags update must happen after the memory write (precise |
| 882 | exception support) */ | 1156 | exception support) */ |
| @@ -891,7 +1165,7 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c) | @@ -891,7 +1165,7 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c) | ||
| 891 | if (d != OR_TMP0) | 1165 | if (d != OR_TMP0) |
| 892 | gen_op_mov_TN_reg[ot][0][d](); | 1166 | gen_op_mov_TN_reg[ot][0][d](); |
| 893 | else | 1167 | else |
| 894 | - gen_op_ld_T0_A0[ot](); | 1168 | + gen_op_ld_T0_A0[ot + s1->mem_index](); |
| 895 | if (s1->cc_op != CC_OP_DYNAMIC) | 1169 | if (s1->cc_op != CC_OP_DYNAMIC) |
| 896 | gen_op_set_cc_op(s1->cc_op); | 1170 | gen_op_set_cc_op(s1->cc_op); |
| 897 | if (c > 0) { | 1171 | if (c > 0) { |
| @@ -904,7 +1178,7 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c) | @@ -904,7 +1178,7 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c) | ||
| 904 | if (d != OR_TMP0) | 1178 | if (d != OR_TMP0) |
| 905 | gen_op_mov_reg_T0[ot][d](); | 1179 | gen_op_mov_reg_T0[ot][d](); |
| 906 | else | 1180 | else |
| 907 | - gen_op_st_T0_A0[ot](); | 1181 | + gen_op_st_T0_A0[ot + s1->mem_index](); |
| 908 | gen_op_update_inc_cc(); | 1182 | gen_op_update_inc_cc(); |
| 909 | } | 1183 | } |
| 910 | 1184 | ||
| @@ -913,7 +1187,7 @@ static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) | @@ -913,7 +1187,7 @@ static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) | ||
| 913 | if (d != OR_TMP0) | 1187 | if (d != OR_TMP0) |
| 914 | gen_op_mov_TN_reg[ot][0][d](); | 1188 | gen_op_mov_TN_reg[ot][0][d](); |
| 915 | else | 1189 | else |
| 916 | - gen_op_ld_T0_A0[ot](); | 1190 | + gen_op_ld_T0_A0[ot + s1->mem_index](); |
| 917 | if (s != OR_TMP1) | 1191 | if (s != OR_TMP1) |
| 918 | gen_op_mov_TN_reg[ot][1][s](); | 1192 | gen_op_mov_TN_reg[ot][1][s](); |
| 919 | /* for zero counts, flags are not updated, so must do it dynamically */ | 1193 | /* for zero counts, flags are not updated, so must do it dynamically */ |
| @@ -1107,9 +1381,9 @@ static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_s | @@ -1107,9 +1381,9 @@ static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_s | ||
| 1107 | if (is_store) { | 1381 | if (is_store) { |
| 1108 | if (reg != OR_TMP0) | 1382 | if (reg != OR_TMP0) |
| 1109 | gen_op_mov_TN_reg[ot][0][reg](); | 1383 | gen_op_mov_TN_reg[ot][0][reg](); |
| 1110 | - gen_op_st_T0_A0[ot](); | 1384 | + gen_op_st_T0_A0[ot + s->mem_index](); |
| 1111 | } else { | 1385 | } else { |
| 1112 | - gen_op_ld_T0_A0[ot](); | 1386 | + gen_op_ld_T0_A0[ot + s->mem_index](); |
| 1113 | if (reg != OR_TMP0) | 1387 | if (reg != OR_TMP0) |
| 1114 | gen_op_mov_reg_T0[ot][reg](); | 1388 | gen_op_mov_reg_T0[ot][reg](); |
| 1115 | } | 1389 | } |
| @@ -1376,7 +1650,7 @@ static void gen_pusha(DisasContext *s) | @@ -1376,7 +1650,7 @@ static void gen_pusha(DisasContext *s) | ||
| 1376 | gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); | 1650 | gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); |
| 1377 | for(i = 0;i < 8; i++) { | 1651 | for(i = 0;i < 8; i++) { |
| 1378 | gen_op_mov_TN_reg[OT_LONG][0][7 - i](); | 1652 | gen_op_mov_TN_reg[OT_LONG][0][7 - i](); |
| 1379 | - gen_op_st_T0_A0[OT_WORD + s->dflag](); | 1653 | + gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index](); |
| 1380 | gen_op_addl_A0_im(2 << s->dflag); | 1654 | gen_op_addl_A0_im(2 << s->dflag); |
| 1381 | } | 1655 | } |
| 1382 | gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP](); | 1656 | gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP](); |
| @@ -1396,7 +1670,7 @@ static void gen_popa(DisasContext *s) | @@ -1396,7 +1670,7 @@ static void gen_popa(DisasContext *s) | ||
| 1396 | for(i = 0;i < 8; i++) { | 1670 | for(i = 0;i < 8; i++) { |
| 1397 | /* ESP is not reloaded */ | 1671 | /* ESP is not reloaded */ |
| 1398 | if (i != 3) { | 1672 | if (i != 3) { |
| 1399 | - gen_op_ld_T0_A0[OT_WORD + s->dflag](); | 1673 | + gen_op_ld_T0_A0[OT_WORD + s->dflag + s->mem_index](); |
| 1400 | gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i](); | 1674 | gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i](); |
| 1401 | } | 1675 | } |
| 1402 | gen_op_addl_A0_im(2 << s->dflag); | 1676 | gen_op_addl_A0_im(2 << s->dflag); |
| @@ -1424,17 +1698,17 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) | @@ -1424,17 +1698,17 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) | ||
| 1424 | gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); | 1698 | gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); |
| 1425 | /* push bp */ | 1699 | /* push bp */ |
| 1426 | gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); | 1700 | gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); |
| 1427 | - gen_op_st_T0_A0[ot](); | 1701 | + gen_op_st_T0_A0[ot + s->mem_index](); |
| 1428 | if (level) { | 1702 | if (level) { |
| 1429 | while (level--) { | 1703 | while (level--) { |
| 1430 | gen_op_addl_A0_im(-opsize); | 1704 | gen_op_addl_A0_im(-opsize); |
| 1431 | gen_op_addl_T0_im(-opsize); | 1705 | gen_op_addl_T0_im(-opsize); |
| 1432 | - gen_op_st_T0_A0[ot](); | 1706 | + gen_op_st_T0_A0[ot + s->mem_index](); |
| 1433 | } | 1707 | } |
| 1434 | gen_op_addl_A0_im(-opsize); | 1708 | gen_op_addl_A0_im(-opsize); |
| 1435 | /* XXX: add st_T1_A0 ? */ | 1709 | /* XXX: add st_T1_A0 ? */ |
| 1436 | gen_op_movl_T0_T1(); | 1710 | gen_op_movl_T0_T1(); |
| 1437 | - gen_op_st_T0_A0[ot](); | 1711 | + gen_op_st_T0_A0[ot + s->mem_index](); |
| 1438 | } | 1712 | } |
| 1439 | gen_op_mov_reg_T1[ot][R_EBP](); | 1713 | gen_op_mov_reg_T1[ot][R_EBP](); |
| 1440 | addend = -esp_addend; | 1714 | addend = -esp_addend; |
| @@ -1613,7 +1887,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1613,7 +1887,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1613 | rm = modrm & 7; | 1887 | rm = modrm & 7; |
| 1614 | if (mod != 3) { | 1888 | if (mod != 3) { |
| 1615 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 1889 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 1616 | - gen_op_ld_T1_A0[ot](); | 1890 | + gen_op_ld_T1_A0[ot + s->mem_index](); |
| 1617 | } else if (op == OP_XORL && rm == reg) { | 1891 | } else if (op == OP_XORL && rm == reg) { |
| 1618 | goto xor_zero; | 1892 | goto xor_zero; |
| 1619 | } else { | 1893 | } else { |
| @@ -1691,7 +1965,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1691,7 +1965,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1691 | op = (modrm >> 3) & 7; | 1965 | op = (modrm >> 3) & 7; |
| 1692 | if (mod != 3) { | 1966 | if (mod != 3) { |
| 1693 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 1967 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 1694 | - gen_op_ld_T0_A0[ot](); | 1968 | + gen_op_ld_T0_A0[ot + s->mem_index](); |
| 1695 | } else { | 1969 | } else { |
| 1696 | gen_op_mov_TN_reg[ot][0][rm](); | 1970 | gen_op_mov_TN_reg[ot][0][rm](); |
| 1697 | } | 1971 | } |
| @@ -1706,7 +1980,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1706,7 +1980,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1706 | case 2: /* not */ | 1980 | case 2: /* not */ |
| 1707 | gen_op_notl_T0(); | 1981 | gen_op_notl_T0(); |
| 1708 | if (mod != 3) { | 1982 | if (mod != 3) { |
| 1709 | - gen_op_st_T0_A0[ot](); | 1983 | + gen_op_st_T0_A0[ot + s->mem_index](); |
| 1710 | } else { | 1984 | } else { |
| 1711 | gen_op_mov_reg_T0[ot][rm](); | 1985 | gen_op_mov_reg_T0[ot][rm](); |
| 1712 | } | 1986 | } |
| @@ -1714,7 +1988,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1714,7 +1988,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1714 | case 3: /* neg */ | 1988 | case 3: /* neg */ |
| 1715 | gen_op_negl_T0(); | 1989 | gen_op_negl_T0(); |
| 1716 | if (mod != 3) { | 1990 | if (mod != 3) { |
| 1717 | - gen_op_st_T0_A0[ot](); | 1991 | + gen_op_st_T0_A0[ot + s->mem_index](); |
| 1718 | } else { | 1992 | } else { |
| 1719 | gen_op_mov_reg_T0[ot][rm](); | 1993 | gen_op_mov_reg_T0[ot][rm](); |
| 1720 | } | 1994 | } |
| @@ -1801,7 +2075,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1801,7 +2075,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1801 | if (mod != 3) { | 2075 | if (mod != 3) { |
| 1802 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 2076 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 1803 | if (op >= 2 && op != 3 && op != 5) | 2077 | if (op >= 2 && op != 3 && op != 5) |
| 1804 | - gen_op_ld_T0_A0[ot](); | 2078 | + gen_op_ld_T0_A0[ot + s->mem_index](); |
| 1805 | } else { | 2079 | } else { |
| 1806 | gen_op_mov_TN_reg[ot][0][rm](); | 2080 | gen_op_mov_TN_reg[ot][0][rm](); |
| 1807 | } | 2081 | } |
| @@ -1832,9 +2106,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1832,9 +2106,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1832 | s->is_jmp = 1; | 2106 | s->is_jmp = 1; |
| 1833 | break; | 2107 | break; |
| 1834 | case 3: /* lcall Ev */ | 2108 | case 3: /* lcall Ev */ |
| 1835 | - gen_op_ld_T1_A0[ot](); | 2109 | + gen_op_ld_T1_A0[ot + s->mem_index](); |
| 1836 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); | 2110 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
| 1837 | - gen_op_lduw_T0_A0(); | 2111 | + gen_op_ld_T0_A0[OT_WORD + s->mem_index](); |
| 1838 | do_lcall: | 2112 | do_lcall: |
| 1839 | if (s->pe && !s->vm86) { | 2113 | if (s->pe && !s->vm86) { |
| 1840 | if (s->cc_op != CC_OP_DYNAMIC) | 2114 | if (s->cc_op != CC_OP_DYNAMIC) |
| @@ -1853,7 +2127,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1853,7 +2127,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1853 | s->is_jmp = 1; | 2127 | s->is_jmp = 1; |
| 1854 | break; | 2128 | break; |
| 1855 | case 5: /* ljmp Ev */ | 2129 | case 5: /* ljmp Ev */ |
| 1856 | - gen_op_ld_T1_A0[ot](); | 2130 | + gen_op_ld_T1_A0[ot + s->mem_index](); |
| 1857 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); | 2131 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
| 1858 | gen_op_lduw_T0_A0(); | 2132 | gen_op_lduw_T0_A0(); |
| 1859 | do_ljmp: | 2133 | do_ljmp: |
| @@ -1965,9 +2239,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1965,9 +2239,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1965 | } else { | 2239 | } else { |
| 1966 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 2240 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 1967 | gen_op_mov_TN_reg[ot][0][reg](); | 2241 | gen_op_mov_TN_reg[ot][0][reg](); |
| 1968 | - gen_op_ld_T1_A0[ot](); | 2242 | + gen_op_ld_T1_A0[ot + s->mem_index](); |
| 1969 | gen_op_addl_T0_T1(); | 2243 | gen_op_addl_T0_T1(); |
| 1970 | - gen_op_st_T0_A0[ot](); | 2244 | + gen_op_st_T0_A0[ot + s->mem_index](); |
| 1971 | gen_op_mov_reg_T1[ot][reg](); | 2245 | gen_op_mov_reg_T1[ot][reg](); |
| 1972 | } | 2246 | } |
| 1973 | gen_op_update2_cc(); | 2247 | gen_op_update2_cc(); |
| @@ -1990,7 +2264,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1990,7 +2264,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1990 | gen_op_mov_reg_T0[ot][rm](); | 2264 | gen_op_mov_reg_T0[ot][rm](); |
| 1991 | } else { | 2265 | } else { |
| 1992 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 2266 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 1993 | - gen_op_ld_T0_A0[ot](); | 2267 | + gen_op_ld_T0_A0[ot + s->mem_index](); |
| 1994 | gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot](); | 2268 | gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot](); |
| 1995 | } | 2269 | } |
| 1996 | s->cc_op = CC_OP_SUBB + ot; | 2270 | s->cc_op = CC_OP_SUBB + ot; |
| @@ -2121,7 +2395,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2121,7 +2395,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2121 | val = insn_get(s, ot); | 2395 | val = insn_get(s, ot); |
| 2122 | gen_op_movl_T0_im(val); | 2396 | gen_op_movl_T0_im(val); |
| 2123 | if (mod != 3) | 2397 | if (mod != 3) |
| 2124 | - gen_op_st_T0_A0[ot](); | 2398 | + gen_op_st_T0_A0[ot + s->mem_index](); |
| 2125 | else | 2399 | else |
| 2126 | gen_op_mov_reg_T0[ot][modrm & 7](); | 2400 | gen_op_mov_reg_T0[ot][modrm & 7](); |
| 2127 | break; | 2401 | break; |
| @@ -2195,9 +2469,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2195,9 +2469,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2195 | } else { | 2469 | } else { |
| 2196 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 2470 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 2197 | if (b & 8) { | 2471 | if (b & 8) { |
| 2198 | - gen_op_lds_T0_A0[ot](); | 2472 | + gen_op_lds_T0_A0[ot + s->mem_index](); |
| 2199 | } else { | 2473 | } else { |
| 2200 | - gen_op_ldu_T0_A0[ot](); | 2474 | + gen_op_ldu_T0_A0[ot + s->mem_index](); |
| 2201 | } | 2475 | } |
| 2202 | gen_op_mov_reg_T0[d_ot][reg](); | 2476 | gen_op_mov_reg_T0[d_ot][reg](); |
| 2203 | } | 2477 | } |
| @@ -2245,11 +2519,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2245,11 +2519,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2245 | } | 2519 | } |
| 2246 | } | 2520 | } |
| 2247 | if ((b & 2) == 0) { | 2521 | if ((b & 2) == 0) { |
| 2248 | - gen_op_ld_T0_A0[ot](); | 2522 | + gen_op_ld_T0_A0[ot + s->mem_index](); |
| 2249 | gen_op_mov_reg_T0[ot][R_EAX](); | 2523 | gen_op_mov_reg_T0[ot][R_EAX](); |
| 2250 | } else { | 2524 | } else { |
| 2251 | gen_op_mov_TN_reg[ot][0][R_EAX](); | 2525 | gen_op_mov_TN_reg[ot][0][R_EAX](); |
| 2252 | - gen_op_st_T0_A0[ot](); | 2526 | + gen_op_st_T0_A0[ot + s->mem_index](); |
| 2253 | } | 2527 | } |
| 2254 | break; | 2528 | break; |
| 2255 | case 0xd7: /* xlat */ | 2529 | case 0xd7: /* xlat */ |
| @@ -2272,7 +2546,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2272,7 +2546,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2272 | gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); | 2546 | gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
| 2273 | } | 2547 | } |
| 2274 | } | 2548 | } |
| 2275 | - gen_op_ldub_T0_A0(); | 2549 | + gen_op_ldu_T0_A0[OT_BYTE + s->mem_index](); |
| 2276 | gen_op_mov_reg_T0[OT_BYTE][R_EAX](); | 2550 | gen_op_mov_reg_T0[OT_BYTE][R_EAX](); |
| 2277 | break; | 2551 | break; |
| 2278 | case 0xb0 ... 0xb7: /* mov R, Ib */ | 2552 | case 0xb0 ... 0xb7: /* mov R, Ib */ |
| @@ -2315,8 +2589,8 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2315,8 +2589,8 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2315 | /* for xchg, lock is implicit */ | 2589 | /* for xchg, lock is implicit */ |
| 2316 | if (!(prefixes & PREFIX_LOCK)) | 2590 | if (!(prefixes & PREFIX_LOCK)) |
| 2317 | gen_op_lock(); | 2591 | gen_op_lock(); |
| 2318 | - gen_op_ld_T1_A0[ot](); | ||
| 2319 | - gen_op_st_T0_A0[ot](); | 2592 | + gen_op_ld_T1_A0[ot + s->mem_index](); |
| 2593 | + gen_op_st_T0_A0[ot + s->mem_index](); | ||
| 2320 | if (!(prefixes & PREFIX_LOCK)) | 2594 | if (!(prefixes & PREFIX_LOCK)) |
| 2321 | gen_op_unlock(); | 2595 | gen_op_unlock(); |
| 2322 | gen_op_mov_reg_T1[ot][reg](); | 2596 | gen_op_mov_reg_T1[ot][reg](); |
| @@ -2344,7 +2618,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2344,7 +2618,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2344 | if (mod == 3) | 2618 | if (mod == 3) |
| 2345 | goto illegal_op; | 2619 | goto illegal_op; |
| 2346 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 2620 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 2347 | - gen_op_ld_T1_A0[ot](); | 2621 | + gen_op_ld_T1_A0[ot + s->mem_index](); |
| 2348 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); | 2622 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
| 2349 | /* load the segment first to handle exceptions properly */ | 2623 | /* load the segment first to handle exceptions properly */ |
| 2350 | gen_op_lduw_T0_A0(); | 2624 | gen_op_lduw_T0_A0(); |
| @@ -2424,7 +2698,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2424,7 +2698,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2424 | 2698 | ||
| 2425 | if (mod != 3) { | 2699 | if (mod != 3) { |
| 2426 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 2700 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 2427 | - gen_op_ld_T0_A0[ot](); | 2701 | + gen_op_ld_T0_A0[ot + s->mem_index](); |
| 2428 | } else { | 2702 | } else { |
| 2429 | gen_op_mov_TN_reg[ot][0][rm](); | 2703 | gen_op_mov_TN_reg[ot][0][rm](); |
| 2430 | } | 2704 | } |
| @@ -2869,9 +3143,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2869,9 +3143,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2869 | ot = dflag ? OT_LONG : OT_WORD; | 3143 | ot = dflag ? OT_LONG : OT_WORD; |
| 2870 | 3144 | ||
| 2871 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { | 3145 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
| 2872 | - gen_string_ds(s, ot, gen_op_movs + 9); | 3146 | + gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
| 2873 | } else { | 3147 | } else { |
| 2874 | - gen_string_ds(s, ot, gen_op_movs); | 3148 | + gen_movs(s, ot); |
| 2875 | } | 3149 | } |
| 2876 | break; | 3150 | break; |
| 2877 | 3151 | ||
| @@ -2883,9 +3157,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2883,9 +3157,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2883 | ot = dflag ? OT_LONG : OT_WORD; | 3157 | ot = dflag ? OT_LONG : OT_WORD; |
| 2884 | 3158 | ||
| 2885 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { | 3159 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
| 2886 | - gen_string_es(s, ot, gen_op_stos + 9); | 3160 | + gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
| 2887 | } else { | 3161 | } else { |
| 2888 | - gen_string_es(s, ot, gen_op_stos); | 3162 | + gen_stos(s, ot); |
| 2889 | } | 3163 | } |
| 2890 | break; | 3164 | break; |
| 2891 | case 0xac: /* lodsS */ | 3165 | case 0xac: /* lodsS */ |
| @@ -2895,9 +3169,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2895,9 +3169,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2895 | else | 3169 | else |
| 2896 | ot = dflag ? OT_LONG : OT_WORD; | 3170 | ot = dflag ? OT_LONG : OT_WORD; |
| 2897 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { | 3171 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
| 2898 | - gen_string_ds(s, ot, gen_op_lods + 9); | 3172 | + gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
| 2899 | } else { | 3173 | } else { |
| 2900 | - gen_string_ds(s, ot, gen_op_lods); | 3174 | + gen_lods(s, ot); |
| 2901 | } | 3175 | } |
| 2902 | break; | 3176 | break; |
| 2903 | case 0xae: /* scasS */ | 3177 | case 0xae: /* scasS */ |
| @@ -2909,15 +3183,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2909,15 +3183,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2909 | if (prefixes & PREFIX_REPNZ) { | 3183 | if (prefixes & PREFIX_REPNZ) { |
| 2910 | if (s->cc_op != CC_OP_DYNAMIC) | 3184 | if (s->cc_op != CC_OP_DYNAMIC) |
| 2911 | gen_op_set_cc_op(s->cc_op); | 3185 | gen_op_set_cc_op(s->cc_op); |
| 2912 | - gen_string_es(s, ot, gen_op_scas + 9 * 2); | 3186 | + gen_string_es(s, ot, gen_op_scas + STRINGOP_NB); |
| 2913 | s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ | 3187 | s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
| 2914 | } else if (prefixes & PREFIX_REPZ) { | 3188 | } else if (prefixes & PREFIX_REPZ) { |
| 2915 | if (s->cc_op != CC_OP_DYNAMIC) | 3189 | if (s->cc_op != CC_OP_DYNAMIC) |
| 2916 | gen_op_set_cc_op(s->cc_op); | 3190 | gen_op_set_cc_op(s->cc_op); |
| 2917 | - gen_string_es(s, ot, gen_op_scas + 9); | 3191 | + gen_string_es(s, ot, gen_op_scas); |
| 2918 | s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ | 3192 | s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
| 2919 | } else { | 3193 | } else { |
| 2920 | - gen_string_es(s, ot, gen_op_scas); | 3194 | + gen_scas(s, ot); |
| 2921 | s->cc_op = CC_OP_SUBB + ot; | 3195 | s->cc_op = CC_OP_SUBB + ot; |
| 2922 | } | 3196 | } |
| 2923 | break; | 3197 | break; |
| @@ -2931,15 +3205,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2931,15 +3205,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2931 | if (prefixes & PREFIX_REPNZ) { | 3205 | if (prefixes & PREFIX_REPNZ) { |
| 2932 | if (s->cc_op != CC_OP_DYNAMIC) | 3206 | if (s->cc_op != CC_OP_DYNAMIC) |
| 2933 | gen_op_set_cc_op(s->cc_op); | 3207 | gen_op_set_cc_op(s->cc_op); |
| 2934 | - gen_string_ds(s, ot, gen_op_cmps + 9 * 2); | 3208 | + gen_string_ds(s, ot, gen_op_cmps + STRINGOP_NB); |
| 2935 | s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ | 3209 | s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
| 2936 | } else if (prefixes & PREFIX_REPZ) { | 3210 | } else if (prefixes & PREFIX_REPZ) { |
| 2937 | if (s->cc_op != CC_OP_DYNAMIC) | 3211 | if (s->cc_op != CC_OP_DYNAMIC) |
| 2938 | gen_op_set_cc_op(s->cc_op); | 3212 | gen_op_set_cc_op(s->cc_op); |
| 2939 | - gen_string_ds(s, ot, gen_op_cmps + 9); | 3213 | + gen_string_ds(s, ot, gen_op_cmps); |
| 2940 | s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ | 3214 | s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
| 2941 | } else { | 3215 | } else { |
| 2942 | - gen_string_ds(s, ot, gen_op_cmps); | 3216 | + gen_cmps(s, ot); |
| 2943 | s->cc_op = CC_OP_SUBB + ot; | 3217 | s->cc_op = CC_OP_SUBB + ot; |
| 2944 | } | 3218 | } |
| 2945 | break; | 3219 | break; |
| @@ -2954,9 +3228,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2954,9 +3228,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2954 | else | 3228 | else |
| 2955 | ot = dflag ? OT_LONG : OT_WORD; | 3229 | ot = dflag ? OT_LONG : OT_WORD; |
| 2956 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { | 3230 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
| 2957 | - gen_string_es(s, ot, gen_op_ins + 9); | 3231 | + gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
| 2958 | } else { | 3232 | } else { |
| 2959 | - gen_string_es(s, ot, gen_op_ins); | 3233 | + gen_ins(s, ot); |
| 2960 | } | 3234 | } |
| 2961 | } | 3235 | } |
| 2962 | break; | 3236 | break; |
| @@ -2971,9 +3245,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2971,9 +3245,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2971 | else | 3245 | else |
| 2972 | ot = dflag ? OT_LONG : OT_WORD; | 3246 | ot = dflag ? OT_LONG : OT_WORD; |
| 2973 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { | 3247 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
| 2974 | - gen_string_ds(s, ot, gen_op_outs + 9); | 3248 | + gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
| 2975 | } else { | 3249 | } else { |
| 2976 | - gen_string_ds(s, ot, gen_op_outs); | 3250 | + gen_outs(s, ot); |
| 2977 | } | 3251 | } |
| 2978 | } | 3252 | } |
| 2979 | break; | 3253 | break; |
| @@ -3071,7 +3345,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3071,7 +3345,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3071 | } else { | 3345 | } else { |
| 3072 | gen_stack_A0(s); | 3346 | gen_stack_A0(s); |
| 3073 | /* pop offset */ | 3347 | /* pop offset */ |
| 3074 | - gen_op_ld_T0_A0[1 + s->dflag](); | 3348 | + gen_op_ld_T0_A0[1 + s->dflag + s->mem_index](); |
| 3075 | if (s->dflag == 0) | 3349 | if (s->dflag == 0) |
| 3076 | gen_op_andl_T0_ffff(); | 3350 | gen_op_andl_T0_ffff(); |
| 3077 | /* NOTE: keeping EIP updated is not a problem in case of | 3351 | /* NOTE: keeping EIP updated is not a problem in case of |
| @@ -3079,7 +3353,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3079,7 +3353,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3079 | gen_op_jmp_T0(); | 3353 | gen_op_jmp_T0(); |
| 3080 | /* pop selector */ | 3354 | /* pop selector */ |
| 3081 | gen_op_addl_A0_im(2 << s->dflag); | 3355 | gen_op_addl_A0_im(2 << s->dflag); |
| 3082 | - gen_op_ld_T0_A0[1 + s->dflag](); | 3356 | + gen_op_ld_T0_A0[1 + s->dflag + s->mem_index](); |
| 3083 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); | 3357 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); |
| 3084 | /* add stack offset */ | 3358 | /* add stack offset */ |
| 3085 | gen_stack_update(s, val + (4 << s->dflag)); | 3359 | gen_stack_update(s, val + (4 << s->dflag)); |
| @@ -3188,7 +3462,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3188,7 +3462,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3188 | gen_setcc(s, b); | 3462 | gen_setcc(s, b); |
| 3189 | if (mod != 3) { | 3463 | if (mod != 3) { |
| 3190 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 3464 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 3191 | - gen_op_ld_T1_A0[ot](); | 3465 | + gen_op_ld_T1_A0[ot + s->mem_index](); |
| 3192 | } else { | 3466 | } else { |
| 3193 | rm = modrm & 7; | 3467 | rm = modrm & 7; |
| 3194 | gen_op_mov_TN_reg[ot][1][rm](); | 3468 | gen_op_mov_TN_reg[ot][1][rm](); |
| @@ -3279,7 +3553,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3279,7 +3553,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3279 | rm = modrm & 7; | 3553 | rm = modrm & 7; |
| 3280 | if (mod != 3) { | 3554 | if (mod != 3) { |
| 3281 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 3555 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 3282 | - gen_op_ld_T0_A0[ot](); | 3556 | + gen_op_ld_T0_A0[ot + s->mem_index](); |
| 3283 | } else { | 3557 | } else { |
| 3284 | gen_op_mov_TN_reg[ot][0][rm](); | 3558 | gen_op_mov_TN_reg[ot][0][rm](); |
| 3285 | } | 3559 | } |
| @@ -3293,7 +3567,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3293,7 +3567,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3293 | s->cc_op = CC_OP_SARB + ot; | 3567 | s->cc_op = CC_OP_SARB + ot; |
| 3294 | if (op != 0) { | 3568 | if (op != 0) { |
| 3295 | if (mod != 3) | 3569 | if (mod != 3) |
| 3296 | - gen_op_st_T0_A0[ot](); | 3570 | + gen_op_st_T0_A0[ot + s->mem_index](); |
| 3297 | else | 3571 | else |
| 3298 | gen_op_mov_reg_T0[ot][rm](); | 3572 | gen_op_mov_reg_T0[ot][rm](); |
| 3299 | gen_op_update_bt_cc(); | 3573 | gen_op_update_bt_cc(); |
| @@ -3324,7 +3598,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3324,7 +3598,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3324 | gen_op_add_bitw_A0_T1(); | 3598 | gen_op_add_bitw_A0_T1(); |
| 3325 | else | 3599 | else |
| 3326 | gen_op_add_bitl_A0_T1(); | 3600 | gen_op_add_bitl_A0_T1(); |
| 3327 | - gen_op_ld_T0_A0[ot](); | 3601 | + gen_op_ld_T0_A0[ot + s->mem_index](); |
| 3328 | } else { | 3602 | } else { |
| 3329 | gen_op_mov_TN_reg[ot][0][rm](); | 3603 | gen_op_mov_TN_reg[ot][0][rm](); |
| 3330 | } | 3604 | } |
| @@ -3332,7 +3606,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3332,7 +3606,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3332 | s->cc_op = CC_OP_SARB + ot; | 3606 | s->cc_op = CC_OP_SARB + ot; |
| 3333 | if (op != 0) { | 3607 | if (op != 0) { |
| 3334 | if (mod != 3) | 3608 | if (mod != 3) |
| 3335 | - gen_op_st_T0_A0[ot](); | 3609 | + gen_op_st_T0_A0[ot + s->mem_index](); |
| 3336 | else | 3610 | else |
| 3337 | gen_op_mov_reg_T0[ot][rm](); | 3611 | gen_op_mov_reg_T0[ot][rm](); |
| 3338 | gen_op_update_bt_cc(); | 3612 | gen_op_update_bt_cc(); |
| @@ -3569,7 +3843,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3569,7 +3843,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3569 | gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit)); | 3843 | gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit)); |
| 3570 | else | 3844 | else |
| 3571 | gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit)); | 3845 | gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit)); |
| 3572 | - gen_op_stw_T0_A0(); | 3846 | + gen_op_st_T0_A0[OT_WORD + s->mem_index](); |
| 3573 | gen_op_addl_A0_im(2); | 3847 | gen_op_addl_A0_im(2); |
| 3574 | if (op == 0) | 3848 | if (op == 0) |
| 3575 | gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base)); | 3849 | gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base)); |
| @@ -3577,7 +3851,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3577,7 +3851,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3577 | gen_op_movl_T0_env(offsetof(CPUX86State,idt.base)); | 3851 | gen_op_movl_T0_env(offsetof(CPUX86State,idt.base)); |
| 3578 | if (!s->dflag) | 3852 | if (!s->dflag) |
| 3579 | gen_op_andl_T0_im(0xffffff); | 3853 | gen_op_andl_T0_im(0xffffff); |
| 3580 | - gen_op_stl_T0_A0(); | 3854 | + gen_op_st_T0_A0[OT_LONG + s->mem_index](); |
| 3581 | break; | 3855 | break; |
| 3582 | case 2: /* lgdt */ | 3856 | case 2: /* lgdt */ |
| 3583 | case 3: /* lidt */ | 3857 | case 3: /* lidt */ |
| @@ -3587,9 +3861,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3587,9 +3861,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3587 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 3861 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 3588 | } else { | 3862 | } else { |
| 3589 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 3863 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 3590 | - gen_op_lduw_T1_A0(); | 3864 | + gen_op_ld_T1_A0[OT_WORD + s->mem_index](); |
| 3591 | gen_op_addl_A0_im(2); | 3865 | gen_op_addl_A0_im(2); |
| 3592 | - gen_op_ldl_T0_A0(); | 3866 | + gen_op_ld_T0_A0[OT_LONG + s->mem_index](); |
| 3593 | if (!s->dflag) | 3867 | if (!s->dflag) |
| 3594 | gen_op_andl_T0_im(0xffffff); | 3868 | gen_op_andl_T0_im(0xffffff); |
| 3595 | if (op == 2) { | 3869 | if (op == 2) { |
| @@ -3990,10 +4264,8 @@ static uint16_t opc_write_flags[NB_OPS] = { | @@ -3990,10 +4264,8 @@ static uint16_t opc_write_flags[NB_OPS] = { | ||
| 3990 | [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \ | 4264 | [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \ |
| 3991 | [INDEX_op_ ## x ## l_a16] = CC_OSZAPC, | 4265 | [INDEX_op_ ## x ## l_a16] = CC_OSZAPC, |
| 3992 | 4266 | ||
| 3993 | - STRINGOP(scas) | ||
| 3994 | STRINGOP(repz_scas) | 4267 | STRINGOP(repz_scas) |
| 3995 | STRINGOP(repnz_scas) | 4268 | STRINGOP(repnz_scas) |
| 3996 | - STRINGOP(cmps) | ||
| 3997 | STRINGOP(repz_cmps) | 4269 | STRINGOP(repz_cmps) |
| 3998 | STRINGOP(repnz_cmps) | 4270 | STRINGOP(repnz_cmps) |
| 3999 | 4271 | ||
| @@ -4050,7 +4322,7 @@ static uint16_t opc_simpler[NB_OPS] = { | @@ -4050,7 +4322,7 @@ static uint16_t opc_simpler[NB_OPS] = { | ||
| 4050 | [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1, | 4322 | [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1, |
| 4051 | }; | 4323 | }; |
| 4052 | 4324 | ||
| 4053 | -static void optimize_flags_init(void) | 4325 | +void optimize_flags_init(void) |
| 4054 | { | 4326 | { |
| 4055 | int i; | 4327 | int i; |
| 4056 | /* put default values in arrays */ | 4328 | /* put default values in arrays */ |
| @@ -4120,6 +4392,14 @@ static inline int gen_intermediate_code_internal(CPUState *env, | @@ -4120,6 +4392,14 @@ static inline int gen_intermediate_code_internal(CPUState *env, | ||
| 4120 | dc->cs_base = cs_base; | 4392 | dc->cs_base = cs_base; |
| 4121 | dc->tb = tb; | 4393 | dc->tb = tb; |
| 4122 | dc->popl_esp_hack = 0; | 4394 | dc->popl_esp_hack = 0; |
| 4395 | + /* select memory access functions */ | ||
| 4396 | + dc->mem_index = 0; | ||
| 4397 | + if ((flags >> GEN_FLAG_SOFT_MMU_SHIFT) & 1) { | ||
| 4398 | + if (dc->cpl == 3) | ||
| 4399 | + dc->mem_index = 6; | ||
| 4400 | + else | ||
| 4401 | + dc->mem_index = 3; | ||
| 4402 | + } | ||
| 4123 | 4403 | ||
| 4124 | gen_opc_ptr = gen_opc_buf; | 4404 | gen_opc_ptr = gen_opc_buf; |
| 4125 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; | 4405 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
| @@ -4234,323 +4514,3 @@ int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) | @@ -4234,323 +4514,3 @@ int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) | ||
| 4234 | return gen_intermediate_code_internal(env, tb, 1); | 4514 | return gen_intermediate_code_internal(env, tb, 1); |
| 4235 | } | 4515 | } |
| 4236 | 4516 | ||
| 4237 | -CPUX86State *cpu_x86_init(void) | ||
| 4238 | -{ | ||
| 4239 | - CPUX86State *env; | ||
| 4240 | - int i; | ||
| 4241 | - static int inited; | ||
| 4242 | - | ||
| 4243 | - cpu_exec_init(); | ||
| 4244 | - | ||
| 4245 | - env = malloc(sizeof(CPUX86State)); | ||
| 4246 | - if (!env) | ||
| 4247 | - return NULL; | ||
| 4248 | - memset(env, 0, sizeof(CPUX86State)); | ||
| 4249 | - /* basic FPU init */ | ||
| 4250 | - for(i = 0;i < 8; i++) | ||
| 4251 | - env->fptags[i] = 1; | ||
| 4252 | - env->fpuc = 0x37f; | ||
| 4253 | - /* flags setup : we activate the IRQs by default as in user mode */ | ||
| 4254 | - env->eflags = 0x2 | IF_MASK; | ||
| 4255 | - | ||
| 4256 | - /* init various static tables */ | ||
| 4257 | - if (!inited) { | ||
| 4258 | - inited = 1; | ||
| 4259 | - optimize_flags_init(); | ||
| 4260 | - } | ||
| 4261 | - return env; | ||
| 4262 | -} | ||
| 4263 | - | ||
| 4264 | -void cpu_x86_close(CPUX86State *env) | ||
| 4265 | -{ | ||
| 4266 | - free(env); | ||
| 4267 | -} | ||
| 4268 | - | ||
| 4269 | -/***********************************************************/ | ||
| 4270 | -/* x86 mmu */ | ||
| 4271 | -/* XXX: add PGE support */ | ||
| 4272 | - | ||
| 4273 | -/* called when cr3 or PG bit are modified */ | ||
| 4274 | -static int last_pg_state = -1; | ||
| 4275 | -static int last_pe_state = 0; | ||
| 4276 | -int phys_ram_size; | ||
| 4277 | -int phys_ram_fd; | ||
| 4278 | -uint8_t *phys_ram_base; | ||
| 4279 | - | ||
| 4280 | -void cpu_x86_update_cr0(CPUX86State *env) | ||
| 4281 | -{ | ||
| 4282 | - int pg_state, pe_state; | ||
| 4283 | - void *map_addr; | ||
| 4284 | - | ||
| 4285 | -#ifdef DEBUG_MMU | ||
| 4286 | - printf("CR0 update: CR0=0x%08x\n", env->cr[0]); | ||
| 4287 | -#endif | ||
| 4288 | - pg_state = env->cr[0] & CR0_PG_MASK; | ||
| 4289 | - if (pg_state != last_pg_state) { | ||
| 4290 | - if (!pg_state) { | ||
| 4291 | - /* we map the physical memory at address 0 */ | ||
| 4292 | - | ||
| 4293 | - map_addr = mmap((void *)0, phys_ram_size, PROT_WRITE | PROT_READ, | ||
| 4294 | - MAP_SHARED | MAP_FIXED, phys_ram_fd, 0); | ||
| 4295 | - if (map_addr == MAP_FAILED) { | ||
| 4296 | - fprintf(stderr, | ||
| 4297 | - "Could not map physical memory at host address 0x%08x\n", | ||
| 4298 | - 0); | ||
| 4299 | - exit(1); | ||
| 4300 | - } | ||
| 4301 | - page_set_flags(0, phys_ram_size, | ||
| 4302 | - PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_EXEC); | ||
| 4303 | - } else { | ||
| 4304 | - /* we unmap the physical memory */ | ||
| 4305 | - munmap((void *)0, phys_ram_size); | ||
| 4306 | - page_set_flags(0, phys_ram_size, 0); | ||
| 4307 | - } | ||
| 4308 | - last_pg_state = pg_state; | ||
| 4309 | - } | ||
| 4310 | - pe_state = env->cr[0] & CR0_PE_MASK; | ||
| 4311 | - if (last_pe_state != pe_state) { | ||
| 4312 | - tb_flush(); | ||
| 4313 | - last_pe_state = pe_state; | ||
| 4314 | - } | ||
| 4315 | -} | ||
| 4316 | - | ||
| 4317 | -void cpu_x86_update_cr3(CPUX86State *env) | ||
| 4318 | -{ | ||
| 4319 | - if (env->cr[0] & CR0_PG_MASK) { | ||
| 4320 | -#if defined(DEBUG_MMU) | ||
| 4321 | - printf("CR3 update: CR3=%08x\n", env->cr[3]); | ||
| 4322 | -#endif | ||
| 4323 | - page_unmap(); | ||
| 4324 | - } | ||
| 4325 | -} | ||
| 4326 | - | ||
| 4327 | -void cpu_x86_init_mmu(CPUX86State *env) | ||
| 4328 | -{ | ||
| 4329 | - last_pg_state = -1; | ||
| 4330 | - cpu_x86_update_cr0(env); | ||
| 4331 | -} | ||
| 4332 | - | ||
| 4333 | -/* XXX: also flush 4MB pages */ | ||
| 4334 | -void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr) | ||
| 4335 | -{ | ||
| 4336 | - int flags; | ||
| 4337 | - unsigned long virt_addr; | ||
| 4338 | - | ||
| 4339 | - flags = page_get_flags(addr); | ||
| 4340 | - if (flags & PAGE_VALID) { | ||
| 4341 | - virt_addr = addr & ~0xfff; | ||
| 4342 | - munmap((void *)virt_addr, 4096); | ||
| 4343 | - page_set_flags(virt_addr, virt_addr + 4096, 0); | ||
| 4344 | - } | ||
| 4345 | -} | ||
| 4346 | - | ||
| 4347 | -/* return value: | ||
| 4348 | - -1 = cannot handle fault | ||
| 4349 | - 0 = nothing more to do | ||
| 4350 | - 1 = generate PF fault | ||
| 4351 | -*/ | ||
| 4352 | -int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) | ||
| 4353 | -{ | ||
| 4354 | - uint8_t *pde_ptr, *pte_ptr; | ||
| 4355 | - uint32_t pde, pte, virt_addr; | ||
| 4356 | - int cpl, error_code, is_dirty, is_user, prot, page_size; | ||
| 4357 | - void *map_addr; | ||
| 4358 | - | ||
| 4359 | - cpl = env->cpl; | ||
| 4360 | - is_user = (cpl == 3); | ||
| 4361 | - | ||
| 4362 | -#ifdef DEBUG_MMU | ||
| 4363 | - printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", | ||
| 4364 | - addr, is_write, is_user, env->eip); | ||
| 4365 | -#endif | ||
| 4366 | - | ||
| 4367 | - if (env->user_mode_only) { | ||
| 4368 | - /* user mode only emulation */ | ||
| 4369 | - error_code = 0; | ||
| 4370 | - goto do_fault; | ||
| 4371 | - } | ||
| 4372 | - | ||
| 4373 | - if (!(env->cr[0] & CR0_PG_MASK)) | ||
| 4374 | - return -1; | ||
| 4375 | - | ||
| 4376 | - /* page directory entry */ | ||
| 4377 | - pde_ptr = phys_ram_base + ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)); | ||
| 4378 | - pde = ldl(pde_ptr); | ||
| 4379 | - if (!(pde & PG_PRESENT_MASK)) { | ||
| 4380 | - error_code = 0; | ||
| 4381 | - goto do_fault; | ||
| 4382 | - } | ||
| 4383 | - if (is_user) { | ||
| 4384 | - if (!(pde & PG_USER_MASK)) | ||
| 4385 | - goto do_fault_protect; | ||
| 4386 | - if (is_write && !(pde & PG_RW_MASK)) | ||
| 4387 | - goto do_fault_protect; | ||
| 4388 | - } else { | ||
| 4389 | - if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) && | ||
| 4390 | - is_write && !(pde & PG_RW_MASK)) | ||
| 4391 | - goto do_fault_protect; | ||
| 4392 | - } | ||
| 4393 | - /* if PSE bit is set, then we use a 4MB page */ | ||
| 4394 | - if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { | ||
| 4395 | - is_dirty = is_write && !(pde & PG_DIRTY_MASK); | ||
| 4396 | - if (!(pde & PG_ACCESSED_MASK)) { | ||
| 4397 | - pde |= PG_ACCESSED_MASK; | ||
| 4398 | - if (is_dirty) | ||
| 4399 | - pde |= PG_DIRTY_MASK; | ||
| 4400 | - stl(pde_ptr, pde); | ||
| 4401 | - } | ||
| 4402 | - | ||
| 4403 | - pte = pde & ~0x003ff000; /* align to 4MB */ | ||
| 4404 | - page_size = 4096 * 1024; | ||
| 4405 | - virt_addr = addr & ~0x003fffff; | ||
| 4406 | - } else { | ||
| 4407 | - if (!(pde & PG_ACCESSED_MASK)) { | ||
| 4408 | - pde |= PG_ACCESSED_MASK; | ||
| 4409 | - stl(pde_ptr, pde); | ||
| 4410 | - } | ||
| 4411 | - | ||
| 4412 | - /* page directory entry */ | ||
| 4413 | - pte_ptr = phys_ram_base + ((pde & ~0xfff) + ((addr >> 10) & 0xffc)); | ||
| 4414 | - pte = ldl(pte_ptr); | ||
| 4415 | - if (!(pte & PG_PRESENT_MASK)) { | ||
| 4416 | - error_code = 0; | ||
| 4417 | - goto do_fault; | ||
| 4418 | - } | ||
| 4419 | - if (is_user) { | ||
| 4420 | - if (!(pte & PG_USER_MASK)) | ||
| 4421 | - goto do_fault_protect; | ||
| 4422 | - if (is_write && !(pte & PG_RW_MASK)) | ||
| 4423 | - goto do_fault_protect; | ||
| 4424 | - } else { | ||
| 4425 | - if ((env->cr[0] & CR0_WP_MASK) && (pte & PG_USER_MASK) && | ||
| 4426 | - is_write && !(pte & PG_RW_MASK)) | ||
| 4427 | - goto do_fault_protect; | ||
| 4428 | - } | ||
| 4429 | - is_dirty = is_write && !(pte & PG_DIRTY_MASK); | ||
| 4430 | - if (!(pte & PG_ACCESSED_MASK) || is_dirty) { | ||
| 4431 | - pte |= PG_ACCESSED_MASK; | ||
| 4432 | - if (is_dirty) | ||
| 4433 | - pte |= PG_DIRTY_MASK; | ||
| 4434 | - stl(pte_ptr, pte); | ||
| 4435 | - } | ||
| 4436 | - page_size = 4096; | ||
| 4437 | - virt_addr = addr & ~0xfff; | ||
| 4438 | - } | ||
| 4439 | - /* the page can be put in the TLB */ | ||
| 4440 | - prot = PROT_READ; | ||
| 4441 | - if (is_user) { | ||
| 4442 | - if (pte & PG_RW_MASK) | ||
| 4443 | - prot |= PROT_WRITE; | ||
| 4444 | - } else { | ||
| 4445 | - if (!(env->cr[0] & CR0_WP_MASK) || !(pte & PG_USER_MASK) || | ||
| 4446 | - (pte & PG_RW_MASK)) | ||
| 4447 | - prot |= PROT_WRITE; | ||
| 4448 | - } | ||
| 4449 | - map_addr = mmap((void *)virt_addr, page_size, prot, | ||
| 4450 | - MAP_SHARED | MAP_FIXED, phys_ram_fd, pte & ~0xfff); | ||
| 4451 | - if (map_addr == MAP_FAILED) { | ||
| 4452 | - fprintf(stderr, | ||
| 4453 | - "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n", | ||
| 4454 | - pte & ~0xfff, virt_addr); | ||
| 4455 | - exit(1); | ||
| 4456 | - } | ||
| 4457 | - page_set_flags(virt_addr, virt_addr + page_size, | ||
| 4458 | - PAGE_VALID | PAGE_EXEC | prot); | ||
| 4459 | -#ifdef DEBUG_MMU | ||
| 4460 | - printf("mmaping 0x%08x to virt 0x%08x pse=%d\n", | ||
| 4461 | - pte & ~0xfff, virt_addr, (page_size != 4096)); | ||
| 4462 | -#endif | ||
| 4463 | - return 0; | ||
| 4464 | - do_fault_protect: | ||
| 4465 | - error_code = PG_ERROR_P_MASK; | ||
| 4466 | - do_fault: | ||
| 4467 | - env->cr[2] = addr; | ||
| 4468 | - env->error_code = (is_write << PG_ERROR_W_BIT) | error_code; | ||
| 4469 | - if (is_user) | ||
| 4470 | - env->error_code |= PG_ERROR_U_MASK; | ||
| 4471 | - return 1; | ||
| 4472 | -} | ||
| 4473 | - | ||
| 4474 | -/***********************************************************/ | ||
| 4475 | -/* x86 debug */ | ||
| 4476 | - | ||
| 4477 | -static const char *cc_op_str[] = { | ||
| 4478 | - "DYNAMIC", | ||
| 4479 | - "EFLAGS", | ||
| 4480 | - "MUL", | ||
| 4481 | - "ADDB", | ||
| 4482 | - "ADDW", | ||
| 4483 | - "ADDL", | ||
| 4484 | - "ADCB", | ||
| 4485 | - "ADCW", | ||
| 4486 | - "ADCL", | ||
| 4487 | - "SUBB", | ||
| 4488 | - "SUBW", | ||
| 4489 | - "SUBL", | ||
| 4490 | - "SBBB", | ||
| 4491 | - "SBBW", | ||
| 4492 | - "SBBL", | ||
| 4493 | - "LOGICB", | ||
| 4494 | - "LOGICW", | ||
| 4495 | - "LOGICL", | ||
| 4496 | - "INCB", | ||
| 4497 | - "INCW", | ||
| 4498 | - "INCL", | ||
| 4499 | - "DECB", | ||
| 4500 | - "DECW", | ||
| 4501 | - "DECL", | ||
| 4502 | - "SHLB", | ||
| 4503 | - "SHLW", | ||
| 4504 | - "SHLL", | ||
| 4505 | - "SARB", | ||
| 4506 | - "SARW", | ||
| 4507 | - "SARL", | ||
| 4508 | -}; | ||
| 4509 | - | ||
| 4510 | -void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags) | ||
| 4511 | -{ | ||
| 4512 | - int eflags; | ||
| 4513 | - char cc_op_name[32]; | ||
| 4514 | - | ||
| 4515 | - eflags = env->eflags; | ||
| 4516 | - fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n" | ||
| 4517 | - "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n" | ||
| 4518 | - "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n", | ||
| 4519 | - env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], | ||
| 4520 | - env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], | ||
| 4521 | - env->eip, eflags, | ||
| 4522 | - eflags & DF_MASK ? 'D' : '-', | ||
| 4523 | - eflags & CC_O ? 'O' : '-', | ||
| 4524 | - eflags & CC_S ? 'S' : '-', | ||
| 4525 | - eflags & CC_Z ? 'Z' : '-', | ||
| 4526 | - eflags & CC_A ? 'A' : '-', | ||
| 4527 | - eflags & CC_P ? 'P' : '-', | ||
| 4528 | - eflags & CC_C ? 'C' : '-'); | ||
| 4529 | - fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n", | ||
| 4530 | - env->segs[R_CS].selector, | ||
| 4531 | - env->segs[R_SS].selector, | ||
| 4532 | - env->segs[R_DS].selector, | ||
| 4533 | - env->segs[R_ES].selector, | ||
| 4534 | - env->segs[R_FS].selector, | ||
| 4535 | - env->segs[R_GS].selector); | ||
| 4536 | - if (flags & X86_DUMP_CCOP) { | ||
| 4537 | - if ((unsigned)env->cc_op < CC_OP_NB) | ||
| 4538 | - strcpy(cc_op_name, cc_op_str[env->cc_op]); | ||
| 4539 | - else | ||
| 4540 | - snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op); | ||
| 4541 | - fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n", | ||
| 4542 | - env->cc_src, env->cc_dst, cc_op_name); | ||
| 4543 | - } | ||
| 4544 | - if (flags & X86_DUMP_FPU) { | ||
| 4545 | - fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", | ||
| 4546 | - (double)env->fpregs[0], | ||
| 4547 | - (double)env->fpregs[1], | ||
| 4548 | - (double)env->fpregs[2], | ||
| 4549 | - (double)env->fpregs[3]); | ||
| 4550 | - fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", | ||
| 4551 | - (double)env->fpregs[4], | ||
| 4552 | - (double)env->fpregs[5], | ||
| 4553 | - (double)env->fpregs[7], | ||
| 4554 | - (double)env->fpregs[8]); | ||
| 4555 | - } | ||
| 4556 | -} |