Commit 42c3c0cceddee64c22024e3e92ed636e75ea9c77
1 parent
9588b95a
native FPU support (disabled)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@641 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
47 additions
and
277 deletions
target-i386/translate-copy.c
... | ... | @@ -31,6 +31,8 @@ |
31 | 31 | #include "exec-all.h" |
32 | 32 | #include "disas.h" |
33 | 33 | |
34 | +#ifdef USE_CODE_COPY | |
35 | + | |
34 | 36 | extern char exec_loop; |
35 | 37 | |
36 | 38 | /* operand size */ |
... | ... | @@ -67,6 +69,7 @@ typedef struct DisasContext { |
67 | 69 | int vm86; /* vm86 mode */ |
68 | 70 | int cpl; |
69 | 71 | int iopl; |
72 | + int flags; | |
70 | 73 | struct TranslationBlock *tb; |
71 | 74 | } DisasContext; |
72 | 75 | |
... | ... | @@ -274,7 +277,7 @@ static int disas_insn(DisasContext *s) |
274 | 277 | uint8_t *pc_start, *pc_tmp, *pc_start_insn; |
275 | 278 | int b, prefixes, aflag, dflag, next_eip, val; |
276 | 279 | int ot; |
277 | - int modrm, mod, op; | |
280 | + int modrm, mod, op, rm; | |
278 | 281 | |
279 | 282 | pc_start = s->pc; |
280 | 283 | prefixes = 0; |
... | ... | @@ -644,48 +647,37 @@ static int disas_insn(DisasContext *s) |
644 | 647 | op = R_GS; |
645 | 648 | do_lxx: |
646 | 649 | goto unsupported_op; |
647 | -#if 0 | |
648 | 650 | /************************/ |
649 | 651 | /* floats */ |
650 | 652 | case 0xd8 ... 0xdf: |
653 | +#if 1 | |
654 | + /* currently not stable enough */ | |
655 | + goto unsupported_op; | |
656 | +#else | |
657 | + if (s->flags & (HF_EM_MASK | HF_TS_MASK)) | |
658 | + goto unsupported_op; | |
659 | +#endif | |
660 | +#if 0 | |
661 | + /* for testing FPU context switch */ | |
662 | + { | |
663 | + static int count; | |
664 | + count = (count + 1) % 3; | |
665 | + if (count != 0) | |
666 | + goto unsupported_op; | |
667 | + } | |
668 | +#endif | |
651 | 669 | modrm = ldub_code(s->pc++); |
652 | 670 | mod = (modrm >> 6) & 3; |
653 | 671 | rm = modrm & 7; |
654 | 672 | op = ((b & 7) << 3) | ((modrm >> 3) & 7); |
655 | 673 | if (mod != 3) { |
656 | 674 | /* memory op */ |
657 | - gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | |
675 | + parse_modrm(s, modrm); | |
658 | 676 | switch(op) { |
659 | 677 | case 0x00 ... 0x07: /* fxxxs */ |
660 | 678 | case 0x10 ... 0x17: /* fixxxl */ |
661 | 679 | case 0x20 ... 0x27: /* fxxxl */ |
662 | 680 | case 0x30 ... 0x37: /* fixxx */ |
663 | - { | |
664 | - int op1; | |
665 | - op1 = op & 7; | |
666 | - | |
667 | - switch(op >> 4) { | |
668 | - case 0: | |
669 | - gen_op_flds_FT0_A0(); | |
670 | - break; | |
671 | - case 1: | |
672 | - gen_op_fildl_FT0_A0(); | |
673 | - break; | |
674 | - case 2: | |
675 | - gen_op_fldl_FT0_A0(); | |
676 | - break; | |
677 | - case 3: | |
678 | - default: | |
679 | - gen_op_fild_FT0_A0(); | |
680 | - break; | |
681 | - } | |
682 | - | |
683 | - gen_op_fp_arith_ST0_FT0[op1](); | |
684 | - if (op1 == 3) { | |
685 | - /* fcomp needs pop */ | |
686 | - gen_op_fpop(); | |
687 | - } | |
688 | - } | |
689 | 681 | break; |
690 | 682 | case 0x08: /* flds */ |
691 | 683 | case 0x0a: /* fsts */ |
... | ... | @@ -699,102 +691,28 @@ static int disas_insn(DisasContext *s) |
699 | 691 | case 0x38: /* filds */ |
700 | 692 | case 0x3a: /* fists */ |
701 | 693 | case 0x3b: /* fistps */ |
702 | - | |
703 | - switch(op & 7) { | |
704 | - case 0: | |
705 | - switch(op >> 4) { | |
706 | - case 0: | |
707 | - gen_op_flds_ST0_A0(); | |
708 | - break; | |
709 | - case 1: | |
710 | - gen_op_fildl_ST0_A0(); | |
711 | - break; | |
712 | - case 2: | |
713 | - gen_op_fldl_ST0_A0(); | |
714 | - break; | |
715 | - case 3: | |
716 | - default: | |
717 | - gen_op_fild_ST0_A0(); | |
718 | - break; | |
719 | - } | |
720 | - break; | |
721 | - default: | |
722 | - switch(op >> 4) { | |
723 | - case 0: | |
724 | - gen_op_fsts_ST0_A0(); | |
725 | - break; | |
726 | - case 1: | |
727 | - gen_op_fistl_ST0_A0(); | |
728 | - break; | |
729 | - case 2: | |
730 | - gen_op_fstl_ST0_A0(); | |
731 | - break; | |
732 | - case 3: | |
733 | - default: | |
734 | - gen_op_fist_ST0_A0(); | |
735 | - break; | |
736 | - } | |
737 | - if ((op & 7) == 3) | |
738 | - gen_op_fpop(); | |
739 | - break; | |
740 | - } | |
741 | - break; | |
742 | 694 | case 0x0c: /* fldenv mem */ |
743 | - gen_op_fldenv_A0(s->dflag); | |
744 | - break; | |
745 | 695 | case 0x0d: /* fldcw mem */ |
746 | - gen_op_fldcw_A0(); | |
747 | - break; | |
748 | 696 | case 0x0e: /* fnstenv mem */ |
749 | - gen_op_fnstenv_A0(s->dflag); | |
750 | - break; | |
751 | 697 | case 0x0f: /* fnstcw mem */ |
752 | - gen_op_fnstcw_A0(); | |
753 | - break; | |
754 | 698 | case 0x1d: /* fldt mem */ |
755 | - gen_op_fldt_ST0_A0(); | |
756 | - break; | |
757 | 699 | case 0x1f: /* fstpt mem */ |
758 | - gen_op_fstt_ST0_A0(); | |
759 | - gen_op_fpop(); | |
760 | - break; | |
761 | 700 | case 0x2c: /* frstor mem */ |
762 | - gen_op_frstor_A0(s->dflag); | |
763 | - break; | |
764 | 701 | case 0x2e: /* fnsave mem */ |
765 | - gen_op_fnsave_A0(s->dflag); | |
766 | - break; | |
767 | 702 | case 0x2f: /* fnstsw mem */ |
768 | - gen_op_fnstsw_A0(); | |
769 | - break; | |
770 | 703 | case 0x3c: /* fbld */ |
771 | - gen_op_fbld_ST0_A0(); | |
772 | - break; | |
773 | 704 | case 0x3e: /* fbstp */ |
774 | - gen_op_fbst_ST0_A0(); | |
775 | - gen_op_fpop(); | |
776 | - break; | |
777 | 705 | case 0x3d: /* fildll */ |
778 | - gen_op_fildll_ST0_A0(); | |
779 | - break; | |
780 | 706 | case 0x3f: /* fistpll */ |
781 | - gen_op_fistll_ST0_A0(); | |
782 | - gen_op_fpop(); | |
783 | 707 | break; |
784 | 708 | default: |
785 | 709 | goto illegal_op; |
786 | 710 | } |
787 | 711 | } else { |
788 | 712 | /* register float ops */ |
789 | - opreg = rm; | |
790 | - | |
791 | 713 | switch(op) { |
792 | 714 | case 0x08: /* fld sti */ |
793 | - gen_op_fpush(); | |
794 | - gen_op_fmov_ST0_STN((opreg + 1) & 7); | |
795 | - break; | |
796 | 715 | case 0x09: /* fxchg sti */ |
797 | - gen_op_fxchg_ST0_STN(opreg); | |
798 | 716 | break; |
799 | 717 | case 0x0a: /* grp d9/2 */ |
800 | 718 | switch(rm) { |
... | ... | @@ -807,149 +725,43 @@ static int disas_insn(DisasContext *s) |
807 | 725 | case 0x0c: /* grp d9/4 */ |
808 | 726 | switch(rm) { |
809 | 727 | case 0: /* fchs */ |
810 | - gen_op_fchs_ST0(); | |
811 | - break; | |
812 | 728 | case 1: /* fabs */ |
813 | - gen_op_fabs_ST0(); | |
814 | - break; | |
815 | 729 | case 4: /* ftst */ |
816 | - gen_op_fldz_FT0(); | |
817 | - gen_op_fcom_ST0_FT0(); | |
818 | - break; | |
819 | 730 | case 5: /* fxam */ |
820 | - gen_op_fxam_ST0(); | |
821 | 731 | break; |
822 | 732 | default: |
823 | 733 | goto illegal_op; |
824 | 734 | } |
825 | 735 | break; |
826 | 736 | case 0x0d: /* grp d9/5 */ |
827 | - { | |
828 | - switch(rm) { | |
829 | - case 0: | |
830 | - gen_op_fpush(); | |
831 | - gen_op_fld1_ST0(); | |
832 | - break; | |
833 | - case 1: | |
834 | - gen_op_fpush(); | |
835 | - gen_op_fldl2t_ST0(); | |
836 | - break; | |
837 | - case 2: | |
838 | - gen_op_fpush(); | |
839 | - gen_op_fldl2e_ST0(); | |
840 | - break; | |
841 | - case 3: | |
842 | - gen_op_fpush(); | |
843 | - gen_op_fldpi_ST0(); | |
844 | - break; | |
845 | - case 4: | |
846 | - gen_op_fpush(); | |
847 | - gen_op_fldlg2_ST0(); | |
848 | - break; | |
849 | - case 5: | |
850 | - gen_op_fpush(); | |
851 | - gen_op_fldln2_ST0(); | |
852 | - break; | |
853 | - case 6: | |
854 | - gen_op_fpush(); | |
855 | - gen_op_fldz_ST0(); | |
856 | - break; | |
857 | - default: | |
858 | - goto illegal_op; | |
859 | - } | |
860 | - } | |
861 | - break; | |
862 | - case 0x0e: /* grp d9/6 */ | |
863 | 737 | switch(rm) { |
864 | - case 0: /* f2xm1 */ | |
865 | - gen_op_f2xm1(); | |
866 | - break; | |
867 | - case 1: /* fyl2x */ | |
868 | - gen_op_fyl2x(); | |
869 | - break; | |
870 | - case 2: /* fptan */ | |
871 | - gen_op_fptan(); | |
872 | - break; | |
873 | - case 3: /* fpatan */ | |
874 | - gen_op_fpatan(); | |
875 | - break; | |
876 | - case 4: /* fxtract */ | |
877 | - gen_op_fxtract(); | |
878 | - break; | |
879 | - case 5: /* fprem1 */ | |
880 | - gen_op_fprem1(); | |
881 | - break; | |
882 | - case 6: /* fdecstp */ | |
883 | - gen_op_fdecstp(); | |
738 | + case 0: | |
739 | + case 1: | |
740 | + case 2: | |
741 | + case 3: | |
742 | + case 4: | |
743 | + case 5: | |
744 | + case 6: | |
884 | 745 | break; |
885 | 746 | default: |
886 | - case 7: /* fincstp */ | |
887 | - gen_op_fincstp(); | |
888 | - break; | |
747 | + goto illegal_op; | |
889 | 748 | } |
890 | 749 | break; |
750 | + case 0x0e: /* grp d9/6 */ | |
751 | + break; | |
891 | 752 | case 0x0f: /* grp d9/7 */ |
892 | - switch(rm) { | |
893 | - case 0: /* fprem */ | |
894 | - gen_op_fprem(); | |
895 | - break; | |
896 | - case 1: /* fyl2xp1 */ | |
897 | - gen_op_fyl2xp1(); | |
898 | - break; | |
899 | - case 2: /* fsqrt */ | |
900 | - gen_op_fsqrt(); | |
901 | - break; | |
902 | - case 3: /* fsincos */ | |
903 | - gen_op_fsincos(); | |
904 | - break; | |
905 | - case 5: /* fscale */ | |
906 | - gen_op_fscale(); | |
907 | - break; | |
908 | - case 4: /* frndint */ | |
909 | - gen_op_frndint(); | |
910 | - break; | |
911 | - case 6: /* fsin */ | |
912 | - gen_op_fsin(); | |
913 | - break; | |
914 | - default: | |
915 | - case 7: /* fcos */ | |
916 | - gen_op_fcos(); | |
917 | - break; | |
918 | - } | |
919 | 753 | break; |
920 | 754 | case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */ |
921 | 755 | case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */ |
922 | 756 | case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */ |
923 | - { | |
924 | - int op1; | |
925 | - | |
926 | - op1 = op & 7; | |
927 | - if (op >= 0x20) { | |
928 | - gen_op_fp_arith_STN_ST0[op1](opreg); | |
929 | - if (op >= 0x30) | |
930 | - gen_op_fpop(); | |
931 | - } else { | |
932 | - gen_op_fmov_FT0_STN(opreg); | |
933 | - gen_op_fp_arith_ST0_FT0[op1](); | |
934 | - } | |
935 | - } | |
936 | 757 | break; |
937 | 758 | case 0x02: /* fcom */ |
938 | - gen_op_fmov_FT0_STN(opreg); | |
939 | - gen_op_fcom_ST0_FT0(); | |
940 | 759 | break; |
941 | 760 | case 0x03: /* fcomp */ |
942 | - gen_op_fmov_FT0_STN(opreg); | |
943 | - gen_op_fcom_ST0_FT0(); | |
944 | - gen_op_fpop(); | |
945 | 761 | break; |
946 | 762 | case 0x15: /* da/5 */ |
947 | 763 | switch(rm) { |
948 | 764 | case 1: /* fucompp */ |
949 | - gen_op_fmov_FT0_STN(1); | |
950 | - gen_op_fucom_ST0_FT0(); | |
951 | - gen_op_fpop(); | |
952 | - gen_op_fpop(); | |
953 | 765 | break; |
954 | 766 | default: |
955 | 767 | goto illegal_op; |
... | ... | @@ -958,15 +770,10 @@ static int disas_insn(DisasContext *s) |
958 | 770 | case 0x1c: |
959 | 771 | switch(rm) { |
960 | 772 | case 0: /* feni (287 only, just do nop here) */ |
961 | - break; | |
962 | 773 | case 1: /* fdisi (287 only, just do nop here) */ |
963 | - break; | |
774 | + goto unsupported_op; | |
964 | 775 | case 2: /* fclex */ |
965 | - gen_op_fclex(); | |
966 | - break; | |
967 | 776 | case 3: /* fninit */ |
968 | - gen_op_fninit(); | |
969 | - break; | |
970 | 777 | case 4: /* fsetpm (287 only, just do nop here) */ |
971 | 778 | break; |
972 | 779 | default: |
... | ... | @@ -974,42 +781,20 @@ static int disas_insn(DisasContext *s) |
974 | 781 | } |
975 | 782 | break; |
976 | 783 | case 0x1d: /* fucomi */ |
977 | - if (s->cc_op != CC_OP_DYNAMIC) | |
978 | - gen_op_set_cc_op(s->cc_op); | |
979 | - gen_op_fmov_FT0_STN(opreg); | |
980 | - gen_op_fucomi_ST0_FT0(); | |
981 | - s->cc_op = CC_OP_EFLAGS; | |
982 | 784 | break; |
983 | 785 | case 0x1e: /* fcomi */ |
984 | - if (s->cc_op != CC_OP_DYNAMIC) | |
985 | - gen_op_set_cc_op(s->cc_op); | |
986 | - gen_op_fmov_FT0_STN(opreg); | |
987 | - gen_op_fcomi_ST0_FT0(); | |
988 | - s->cc_op = CC_OP_EFLAGS; | |
989 | 786 | break; |
990 | 787 | case 0x2a: /* fst sti */ |
991 | - gen_op_fmov_STN_ST0(opreg); | |
992 | 788 | break; |
993 | 789 | case 0x2b: /* fstp sti */ |
994 | - gen_op_fmov_STN_ST0(opreg); | |
995 | - gen_op_fpop(); | |
996 | 790 | break; |
997 | 791 | case 0x2c: /* fucom st(i) */ |
998 | - gen_op_fmov_FT0_STN(opreg); | |
999 | - gen_op_fucom_ST0_FT0(); | |
1000 | 792 | break; |
1001 | 793 | case 0x2d: /* fucomp st(i) */ |
1002 | - gen_op_fmov_FT0_STN(opreg); | |
1003 | - gen_op_fucom_ST0_FT0(); | |
1004 | - gen_op_fpop(); | |
1005 | 794 | break; |
1006 | 795 | case 0x33: /* de/3 */ |
1007 | 796 | switch(rm) { |
1008 | 797 | case 1: /* fcompp */ |
1009 | - gen_op_fmov_FT0_STN(1); | |
1010 | - gen_op_fcom_ST0_FT0(); | |
1011 | - gen_op_fpop(); | |
1012 | - gen_op_fpop(); | |
1013 | 798 | break; |
1014 | 799 | default: |
1015 | 800 | goto illegal_op; |
... | ... | @@ -1018,49 +803,25 @@ static int disas_insn(DisasContext *s) |
1018 | 803 | case 0x3c: /* df/4 */ |
1019 | 804 | switch(rm) { |
1020 | 805 | case 0: |
1021 | - gen_op_fnstsw_EAX(); | |
1022 | 806 | break; |
1023 | 807 | default: |
1024 | 808 | goto illegal_op; |
1025 | 809 | } |
1026 | 810 | break; |
1027 | 811 | case 0x3d: /* fucomip */ |
1028 | - if (s->cc_op != CC_OP_DYNAMIC) | |
1029 | - gen_op_set_cc_op(s->cc_op); | |
1030 | - gen_op_fmov_FT0_STN(opreg); | |
1031 | - gen_op_fucomi_ST0_FT0(); | |
1032 | - gen_op_fpop(); | |
1033 | - s->cc_op = CC_OP_EFLAGS; | |
1034 | 812 | break; |
1035 | 813 | case 0x3e: /* fcomip */ |
1036 | - if (s->cc_op != CC_OP_DYNAMIC) | |
1037 | - gen_op_set_cc_op(s->cc_op); | |
1038 | - gen_op_fmov_FT0_STN(opreg); | |
1039 | - gen_op_fcomi_ST0_FT0(); | |
1040 | - gen_op_fpop(); | |
1041 | - s->cc_op = CC_OP_EFLAGS; | |
1042 | 814 | break; |
1043 | 815 | case 0x10 ... 0x13: /* fcmovxx */ |
1044 | 816 | case 0x18 ... 0x1b: |
1045 | - { | |
1046 | - int op1; | |
1047 | - const static uint8_t fcmov_cc[8] = { | |
1048 | - (JCC_B << 1), | |
1049 | - (JCC_Z << 1), | |
1050 | - (JCC_BE << 1), | |
1051 | - (JCC_P << 1), | |
1052 | - }; | |
1053 | - op1 = fcmov_cc[op & 3] | ((op >> 3) & 1); | |
1054 | - gen_setcc(s, op1); | |
1055 | - gen_op_fcmov_ST0_STN_T0(opreg); | |
1056 | - } | |
1057 | 817 | break; |
1058 | 818 | default: |
1059 | 819 | goto illegal_op; |
1060 | 820 | } |
1061 | 821 | } |
822 | + s->tb->cflags |= CF_TB_FP_USED; | |
1062 | 823 | break; |
1063 | -#endif | |
824 | + | |
1064 | 825 | /**************************/ |
1065 | 826 | /* mov */ |
1066 | 827 | case 0xc6: |
... | ... | @@ -1303,6 +1064,10 @@ static int disas_insn(DisasContext *s) |
1303 | 1064 | case 0x90: /* nop */ |
1304 | 1065 | break; |
1305 | 1066 | case 0x9b: /* fwait */ |
1067 | + if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == | |
1068 | + (HF_MP_MASK | HF_TS_MASK)) { | |
1069 | + goto unsupported_op; | |
1070 | + } | |
1306 | 1071 | break; |
1307 | 1072 | case 0xcc: /* int3 */ |
1308 | 1073 | goto unsupported_op; |
... | ... | @@ -1436,7 +1201,8 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
1436 | 1201 | dc->cpl = (flags >> HF_CPL_SHIFT) & 3; |
1437 | 1202 | dc->iopl = (flags >> IOPL_SHIFT) & 3; |
1438 | 1203 | dc->tb = tb; |
1439 | - | |
1204 | + dc->flags = flags; | |
1205 | + | |
1440 | 1206 | dc->is_jmp = 0; |
1441 | 1207 | |
1442 | 1208 | for(;;) { |
... | ... | @@ -1473,7 +1239,9 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
1473 | 1239 | #ifdef DEBUG_DISAS |
1474 | 1240 | if (loglevel) { |
1475 | 1241 | fprintf(logfile, "----------------\n"); |
1476 | - fprintf(logfile, "IN: COPY: %s\n", lookup_symbol(pc_start)); | |
1242 | + fprintf(logfile, "IN: COPY: %s fpu=%d\n", | |
1243 | + lookup_symbol(pc_start), | |
1244 | + tb->cflags & CF_TB_FP_USED ? 1 : 0); | |
1477 | 1245 | disas(logfile, pc_start, dc->pc - pc_start, 0, !dc->code32); |
1478 | 1246 | fprintf(logfile, "\n"); |
1479 | 1247 | } |
... | ... | @@ -1482,7 +1250,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
1482 | 1250 | if (!search_pc) { |
1483 | 1251 | *gen_code_size_ptr = dc->gen_code_ptr - dc->gen_code_start; |
1484 | 1252 | tb->size = dc->pc - pc_start; |
1485 | - tb->cflags = CF_CODE_COPY; | |
1253 | + tb->cflags |= CF_CODE_COPY; | |
1486 | 1254 | return 0; |
1487 | 1255 | } else { |
1488 | 1256 | return -1; |
... | ... | @@ -1526,7 +1294,7 @@ int cpu_restore_state_copy(TranslationBlock *tb, |
1526 | 1294 | if (ret < 0) |
1527 | 1295 | return ret; |
1528 | 1296 | /* restore all the CPU state from the CPU context from the |
1529 | - signal */ | |
1297 | + signal. The FPU context stays in the host CPU. */ | |
1530 | 1298 | |
1531 | 1299 | env->regs[R_EAX] = uc->uc_mcontext.gregs[REG_EAX]; |
1532 | 1300 | env->regs[R_ECX] = uc->uc_mcontext.gregs[REG_ECX]; |
... | ... | @@ -1542,3 +1310,5 @@ int cpu_restore_state_copy(TranslationBlock *tb, |
1542 | 1310 | env->cc_op = CC_OP_EFLAGS; |
1543 | 1311 | return 0; |
1544 | 1312 | } |
1313 | + | |
1314 | +#endif /* USE_CODE_COPY */ | ... | ... |