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 | -} |