Revision 42c3c0cc
b/target-i386/translate-copy.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 1310 |
env->cc_op = CC_OP_EFLAGS; |
1543 | 1311 |
return 0; |
1544 | 1312 |
} |
1313 |
|
|
1314 |
#endif /* USE_CODE_COPY */ |
Also available in: Unified diff