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 | 30 | #include "exec.h" |
31 | 31 | #include "disas.h" |
32 | 32 | |
33 | -//#define DEBUG_MMU | |
34 | - | |
35 | 33 | /* XXX: move that elsewhere */ |
36 | 34 | static uint16_t *gen_opc_ptr; |
37 | 35 | static uint32_t *gen_opparam_ptr; |
... | ... | @@ -62,6 +60,7 @@ typedef struct DisasContext { |
62 | 60 | int cpl; |
63 | 61 | int iopl; |
64 | 62 | int tf; /* TF cpu flag */ |
63 | + int mem_index; /* select memory access functions */ | |
65 | 64 | struct TranslationBlock *tb; |
66 | 65 | int popl_esp_hack; /* for correct popl with esp base handling */ |
67 | 66 | } DisasContext; |
... | ... | @@ -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 | 568 | gen_op_ldsb_T0_A0, |
570 | 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 | 582 | gen_op_ldub_T0_A0, |
575 | 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 | 597 | gen_op_ldub_T0_A0, |
581 | 598 | gen_op_lduw_T0_A0, |
582 | 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 | 611 | gen_op_ldub_T1_A0, |
587 | 612 | gen_op_lduw_T1_A0, |
588 | 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 | 625 | gen_op_stb_T0_A0, |
593 | 626 | gen_op_stw_T0_A0, |
594 | 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 | 638 | /* the _a32 and _a16 string operations use A0 as the base register. */ |
598 | 639 | |
640 | +#define STRINGOP_NB 9 | |
641 | + | |
599 | 642 | #define STRINGOP(x) \ |
600 | 643 | gen_op_ ## x ## b_fast, \ |
601 | 644 | gen_op_ ## x ## w_fast, \ |
... | ... | @@ -607,44 +650,275 @@ static GenOpFunc *gen_op_st_T0_A0[3] = { |
607 | 650 | gen_op_ ## x ## w_a16, \ |
608 | 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 | 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 | 1107 | if (d != OR_TMP0) { |
834 | 1108 | gen_op_mov_TN_reg[ot][0][d](); |
835 | 1109 | } else { |
836 | - gen_op_ld_T0_A0[ot](); | |
1110 | + gen_op_ld_T0_A0[ot + s1->mem_index](); | |
837 | 1111 | } |
838 | 1112 | switch(op) { |
839 | 1113 | case OP_ADCL: |
... | ... | @@ -876,7 +1150,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) |
876 | 1150 | if (d != OR_TMP0) |
877 | 1151 | gen_op_mov_reg_T0[ot][d](); |
878 | 1152 | else |
879 | - gen_op_st_T0_A0[ot](); | |
1153 | + gen_op_st_T0_A0[ot + s1->mem_index](); | |
880 | 1154 | } |
881 | 1155 | /* the flags update must happen after the memory write (precise |
882 | 1156 | exception support) */ |
... | ... | @@ -891,7 +1165,7 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c) |
891 | 1165 | if (d != OR_TMP0) |
892 | 1166 | gen_op_mov_TN_reg[ot][0][d](); |
893 | 1167 | else |
894 | - gen_op_ld_T0_A0[ot](); | |
1168 | + gen_op_ld_T0_A0[ot + s1->mem_index](); | |
895 | 1169 | if (s1->cc_op != CC_OP_DYNAMIC) |
896 | 1170 | gen_op_set_cc_op(s1->cc_op); |
897 | 1171 | if (c > 0) { |
... | ... | @@ -904,7 +1178,7 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c) |
904 | 1178 | if (d != OR_TMP0) |
905 | 1179 | gen_op_mov_reg_T0[ot][d](); |
906 | 1180 | else |
907 | - gen_op_st_T0_A0[ot](); | |
1181 | + gen_op_st_T0_A0[ot + s1->mem_index](); | |
908 | 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 | 1187 | if (d != OR_TMP0) |
914 | 1188 | gen_op_mov_TN_reg[ot][0][d](); |
915 | 1189 | else |
916 | - gen_op_ld_T0_A0[ot](); | |
1190 | + gen_op_ld_T0_A0[ot + s1->mem_index](); | |
917 | 1191 | if (s != OR_TMP1) |
918 | 1192 | gen_op_mov_TN_reg[ot][1][s](); |
919 | 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 | 1381 | if (is_store) { |
1108 | 1382 | if (reg != OR_TMP0) |
1109 | 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 | 1385 | } else { |
1112 | - gen_op_ld_T0_A0[ot](); | |
1386 | + gen_op_ld_T0_A0[ot + s->mem_index](); | |
1113 | 1387 | if (reg != OR_TMP0) |
1114 | 1388 | gen_op_mov_reg_T0[ot][reg](); |
1115 | 1389 | } |
... | ... | @@ -1376,7 +1650,7 @@ static void gen_pusha(DisasContext *s) |
1376 | 1650 | gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); |
1377 | 1651 | for(i = 0;i < 8; i++) { |
1378 | 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 | 1654 | gen_op_addl_A0_im(2 << s->dflag); |
1381 | 1655 | } |
1382 | 1656 | gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP](); |
... | ... | @@ -1396,7 +1670,7 @@ static void gen_popa(DisasContext *s) |
1396 | 1670 | for(i = 0;i < 8; i++) { |
1397 | 1671 | /* ESP is not reloaded */ |
1398 | 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 | 1674 | gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i](); |
1401 | 1675 | } |
1402 | 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 | 1698 | gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); |
1425 | 1699 | /* push bp */ |
1426 | 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 | 1702 | if (level) { |
1429 | 1703 | while (level--) { |
1430 | 1704 | gen_op_addl_A0_im(-opsize); |
1431 | 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 | 1708 | gen_op_addl_A0_im(-opsize); |
1435 | 1709 | /* XXX: add st_T1_A0 ? */ |
1436 | 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 | 1713 | gen_op_mov_reg_T1[ot][R_EBP](); |
1440 | 1714 | addend = -esp_addend; |
... | ... | @@ -1613,7 +1887,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
1613 | 1887 | rm = modrm & 7; |
1614 | 1888 | if (mod != 3) { |
1615 | 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 | 1891 | } else if (op == OP_XORL && rm == reg) { |
1618 | 1892 | goto xor_zero; |
1619 | 1893 | } else { |
... | ... | @@ -1691,7 +1965,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
1691 | 1965 | op = (modrm >> 3) & 7; |
1692 | 1966 | if (mod != 3) { |
1693 | 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 | 1969 | } else { |
1696 | 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 | 1980 | case 2: /* not */ |
1707 | 1981 | gen_op_notl_T0(); |
1708 | 1982 | if (mod != 3) { |
1709 | - gen_op_st_T0_A0[ot](); | |
1983 | + gen_op_st_T0_A0[ot + s->mem_index](); | |
1710 | 1984 | } else { |
1711 | 1985 | gen_op_mov_reg_T0[ot][rm](); |
1712 | 1986 | } |
... | ... | @@ -1714,7 +1988,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
1714 | 1988 | case 3: /* neg */ |
1715 | 1989 | gen_op_negl_T0(); |
1716 | 1990 | if (mod != 3) { |
1717 | - gen_op_st_T0_A0[ot](); | |
1991 | + gen_op_st_T0_A0[ot + s->mem_index](); | |
1718 | 1992 | } else { |
1719 | 1993 | gen_op_mov_reg_T0[ot][rm](); |
1720 | 1994 | } |
... | ... | @@ -1801,7 +2075,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
1801 | 2075 | if (mod != 3) { |
1802 | 2076 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
1803 | 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 | 2079 | } else { |
1806 | 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 | 2106 | s->is_jmp = 1; |
1833 | 2107 | break; |
1834 | 2108 | case 3: /* lcall Ev */ |
1835 | - gen_op_ld_T1_A0[ot](); | |
2109 | + gen_op_ld_T1_A0[ot + s->mem_index](); | |
1836 | 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 | 2112 | do_lcall: |
1839 | 2113 | if (s->pe && !s->vm86) { |
1840 | 2114 | if (s->cc_op != CC_OP_DYNAMIC) |
... | ... | @@ -1853,7 +2127,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
1853 | 2127 | s->is_jmp = 1; |
1854 | 2128 | break; |
1855 | 2129 | case 5: /* ljmp Ev */ |
1856 | - gen_op_ld_T1_A0[ot](); | |
2130 | + gen_op_ld_T1_A0[ot + s->mem_index](); | |
1857 | 2131 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
1858 | 2132 | gen_op_lduw_T0_A0(); |
1859 | 2133 | do_ljmp: |
... | ... | @@ -1965,9 +2239,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
1965 | 2239 | } else { |
1966 | 2240 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
1967 | 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 | 2243 | gen_op_addl_T0_T1(); |
1970 | - gen_op_st_T0_A0[ot](); | |
2244 | + gen_op_st_T0_A0[ot + s->mem_index](); | |
1971 | 2245 | gen_op_mov_reg_T1[ot][reg](); |
1972 | 2246 | } |
1973 | 2247 | gen_op_update2_cc(); |
... | ... | @@ -1990,7 +2264,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
1990 | 2264 | gen_op_mov_reg_T0[ot][rm](); |
1991 | 2265 | } else { |
1992 | 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 | 2268 | gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot](); |
1995 | 2269 | } |
1996 | 2270 | s->cc_op = CC_OP_SUBB + ot; |
... | ... | @@ -2121,7 +2395,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2121 | 2395 | val = insn_get(s, ot); |
2122 | 2396 | gen_op_movl_T0_im(val); |
2123 | 2397 | if (mod != 3) |
2124 | - gen_op_st_T0_A0[ot](); | |
2398 | + gen_op_st_T0_A0[ot + s->mem_index](); | |
2125 | 2399 | else |
2126 | 2400 | gen_op_mov_reg_T0[ot][modrm & 7](); |
2127 | 2401 | break; |
... | ... | @@ -2195,9 +2469,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2195 | 2469 | } else { |
2196 | 2470 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2197 | 2471 | if (b & 8) { |
2198 | - gen_op_lds_T0_A0[ot](); | |
2472 | + gen_op_lds_T0_A0[ot + s->mem_index](); | |
2199 | 2473 | } else { |
2200 | - gen_op_ldu_T0_A0[ot](); | |
2474 | + gen_op_ldu_T0_A0[ot + s->mem_index](); | |
2201 | 2475 | } |
2202 | 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 | 2519 | } |
2246 | 2520 | } |
2247 | 2521 | if ((b & 2) == 0) { |
2248 | - gen_op_ld_T0_A0[ot](); | |
2522 | + gen_op_ld_T0_A0[ot + s->mem_index](); | |
2249 | 2523 | gen_op_mov_reg_T0[ot][R_EAX](); |
2250 | 2524 | } else { |
2251 | 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 | 2528 | break; |
2255 | 2529 | case 0xd7: /* xlat */ |
... | ... | @@ -2272,7 +2546,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2272 | 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 | 2550 | gen_op_mov_reg_T0[OT_BYTE][R_EAX](); |
2277 | 2551 | break; |
2278 | 2552 | case 0xb0 ... 0xb7: /* mov R, Ib */ |
... | ... | @@ -2315,8 +2589,8 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2315 | 2589 | /* for xchg, lock is implicit */ |
2316 | 2590 | if (!(prefixes & PREFIX_LOCK)) |
2317 | 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 | 2594 | if (!(prefixes & PREFIX_LOCK)) |
2321 | 2595 | gen_op_unlock(); |
2322 | 2596 | gen_op_mov_reg_T1[ot][reg](); |
... | ... | @@ -2344,7 +2618,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2344 | 2618 | if (mod == 3) |
2345 | 2619 | goto illegal_op; |
2346 | 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 | 2622 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
2349 | 2623 | /* load the segment first to handle exceptions properly */ |
2350 | 2624 | gen_op_lduw_T0_A0(); |
... | ... | @@ -2424,7 +2698,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2424 | 2698 | |
2425 | 2699 | if (mod != 3) { |
2426 | 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 | 2702 | } else { |
2429 | 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 | 3143 | ot = dflag ? OT_LONG : OT_WORD; |
2870 | 3144 | |
2871 | 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 | 3147 | } else { |
2874 | - gen_string_ds(s, ot, gen_op_movs); | |
3148 | + gen_movs(s, ot); | |
2875 | 3149 | } |
2876 | 3150 | break; |
2877 | 3151 | |
... | ... | @@ -2883,9 +3157,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2883 | 3157 | ot = dflag ? OT_LONG : OT_WORD; |
2884 | 3158 | |
2885 | 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 | 3161 | } else { |
2888 | - gen_string_es(s, ot, gen_op_stos); | |
3162 | + gen_stos(s, ot); | |
2889 | 3163 | } |
2890 | 3164 | break; |
2891 | 3165 | case 0xac: /* lodsS */ |
... | ... | @@ -2895,9 +3169,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2895 | 3169 | else |
2896 | 3170 | ot = dflag ? OT_LONG : OT_WORD; |
2897 | 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 | 3173 | } else { |
2900 | - gen_string_ds(s, ot, gen_op_lods); | |
3174 | + gen_lods(s, ot); | |
2901 | 3175 | } |
2902 | 3176 | break; |
2903 | 3177 | case 0xae: /* scasS */ |
... | ... | @@ -2909,15 +3183,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2909 | 3183 | if (prefixes & PREFIX_REPNZ) { |
2910 | 3184 | if (s->cc_op != CC_OP_DYNAMIC) |
2911 | 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 | 3187 | s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
2914 | 3188 | } else if (prefixes & PREFIX_REPZ) { |
2915 | 3189 | if (s->cc_op != CC_OP_DYNAMIC) |
2916 | 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 | 3192 | s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
2919 | 3193 | } else { |
2920 | - gen_string_es(s, ot, gen_op_scas); | |
3194 | + gen_scas(s, ot); | |
2921 | 3195 | s->cc_op = CC_OP_SUBB + ot; |
2922 | 3196 | } |
2923 | 3197 | break; |
... | ... | @@ -2931,15 +3205,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2931 | 3205 | if (prefixes & PREFIX_REPNZ) { |
2932 | 3206 | if (s->cc_op != CC_OP_DYNAMIC) |
2933 | 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 | 3209 | s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
2936 | 3210 | } else if (prefixes & PREFIX_REPZ) { |
2937 | 3211 | if (s->cc_op != CC_OP_DYNAMIC) |
2938 | 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 | 3214 | s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ |
2941 | 3215 | } else { |
2942 | - gen_string_ds(s, ot, gen_op_cmps); | |
3216 | + gen_cmps(s, ot); | |
2943 | 3217 | s->cc_op = CC_OP_SUBB + ot; |
2944 | 3218 | } |
2945 | 3219 | break; |
... | ... | @@ -2954,9 +3228,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2954 | 3228 | else |
2955 | 3229 | ot = dflag ? OT_LONG : OT_WORD; |
2956 | 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 | 3232 | } else { |
2959 | - gen_string_es(s, ot, gen_op_ins); | |
3233 | + gen_ins(s, ot); | |
2960 | 3234 | } |
2961 | 3235 | } |
2962 | 3236 | break; |
... | ... | @@ -2971,9 +3245,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2971 | 3245 | else |
2972 | 3246 | ot = dflag ? OT_LONG : OT_WORD; |
2973 | 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 | 3249 | } else { |
2976 | - gen_string_ds(s, ot, gen_op_outs); | |
3250 | + gen_outs(s, ot); | |
2977 | 3251 | } |
2978 | 3252 | } |
2979 | 3253 | break; |
... | ... | @@ -3071,7 +3345,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3071 | 3345 | } else { |
3072 | 3346 | gen_stack_A0(s); |
3073 | 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 | 3349 | if (s->dflag == 0) |
3076 | 3350 | gen_op_andl_T0_ffff(); |
3077 | 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 | 3353 | gen_op_jmp_T0(); |
3080 | 3354 | /* pop selector */ |
3081 | 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 | 3357 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); |
3084 | 3358 | /* add stack offset */ |
3085 | 3359 | gen_stack_update(s, val + (4 << s->dflag)); |
... | ... | @@ -3188,7 +3462,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3188 | 3462 | gen_setcc(s, b); |
3189 | 3463 | if (mod != 3) { |
3190 | 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 | 3466 | } else { |
3193 | 3467 | rm = modrm & 7; |
3194 | 3468 | gen_op_mov_TN_reg[ot][1][rm](); |
... | ... | @@ -3279,7 +3553,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3279 | 3553 | rm = modrm & 7; |
3280 | 3554 | if (mod != 3) { |
3281 | 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 | 3557 | } else { |
3284 | 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 | 3567 | s->cc_op = CC_OP_SARB + ot; |
3294 | 3568 | if (op != 0) { |
3295 | 3569 | if (mod != 3) |
3296 | - gen_op_st_T0_A0[ot](); | |
3570 | + gen_op_st_T0_A0[ot + s->mem_index](); | |
3297 | 3571 | else |
3298 | 3572 | gen_op_mov_reg_T0[ot][rm](); |
3299 | 3573 | gen_op_update_bt_cc(); |
... | ... | @@ -3324,7 +3598,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3324 | 3598 | gen_op_add_bitw_A0_T1(); |
3325 | 3599 | else |
3326 | 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 | 3602 | } else { |
3329 | 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 | 3606 | s->cc_op = CC_OP_SARB + ot; |
3333 | 3607 | if (op != 0) { |
3334 | 3608 | if (mod != 3) |
3335 | - gen_op_st_T0_A0[ot](); | |
3609 | + gen_op_st_T0_A0[ot + s->mem_index](); | |
3336 | 3610 | else |
3337 | 3611 | gen_op_mov_reg_T0[ot][rm](); |
3338 | 3612 | gen_op_update_bt_cc(); |
... | ... | @@ -3569,7 +3843,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3569 | 3843 | gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit)); |
3570 | 3844 | else |
3571 | 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 | 3847 | gen_op_addl_A0_im(2); |
3574 | 3848 | if (op == 0) |
3575 | 3849 | gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base)); |
... | ... | @@ -3577,7 +3851,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3577 | 3851 | gen_op_movl_T0_env(offsetof(CPUX86State,idt.base)); |
3578 | 3852 | if (!s->dflag) |
3579 | 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 | 3855 | break; |
3582 | 3856 | case 2: /* lgdt */ |
3583 | 3857 | case 3: /* lidt */ |
... | ... | @@ -3587,9 +3861,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3587 | 3861 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3588 | 3862 | } else { |
3589 | 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 | 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 | 3867 | if (!s->dflag) |
3594 | 3868 | gen_op_andl_T0_im(0xffffff); |
3595 | 3869 | if (op == 2) { |
... | ... | @@ -3990,10 +4264,8 @@ static uint16_t opc_write_flags[NB_OPS] = { |
3990 | 4264 | [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \ |
3991 | 4265 | [INDEX_op_ ## x ## l_a16] = CC_OSZAPC, |
3992 | 4266 | |
3993 | - STRINGOP(scas) | |
3994 | 4267 | STRINGOP(repz_scas) |
3995 | 4268 | STRINGOP(repnz_scas) |
3996 | - STRINGOP(cmps) | |
3997 | 4269 | STRINGOP(repz_cmps) |
3998 | 4270 | STRINGOP(repnz_cmps) |
3999 | 4271 | |
... | ... | @@ -4050,7 +4322,7 @@ static uint16_t opc_simpler[NB_OPS] = { |
4050 | 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 | 4327 | int i; |
4056 | 4328 | /* put default values in arrays */ |
... | ... | @@ -4120,6 +4392,14 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
4120 | 4392 | dc->cs_base = cs_base; |
4121 | 4393 | dc->tb = tb; |
4122 | 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 | 4404 | gen_opc_ptr = gen_opc_buf; |
4125 | 4405 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
... | ... | @@ -4234,323 +4514,3 @@ int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) |
4234 | 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 | -} | ... | ... |