Revision 8e1c85e3 target-i386/translate.c
b/target-i386/translate.c | ||
---|---|---|
133 | 133 |
OP_SAR = 7, |
134 | 134 |
}; |
135 | 135 |
|
136 |
enum { |
|
137 |
JCC_O, |
|
138 |
JCC_B, |
|
139 |
JCC_Z, |
|
140 |
JCC_BE, |
|
141 |
JCC_S, |
|
142 |
JCC_P, |
|
143 |
JCC_L, |
|
144 |
JCC_LE, |
|
145 |
}; |
|
146 |
|
|
136 | 147 |
/* operand size */ |
137 | 148 |
enum { |
138 | 149 |
OT_BYTE = 0, |
... | ... | |
228 | 239 |
|
229 | 240 |
#define NB_OP_SIZES 4 |
230 | 241 |
|
231 |
#define DEF_REGS(prefix, suffix) \ |
|
232 |
prefix ## EAX ## suffix,\ |
|
233 |
prefix ## ECX ## suffix,\ |
|
234 |
prefix ## EDX ## suffix,\ |
|
235 |
prefix ## EBX ## suffix,\ |
|
236 |
prefix ## ESP ## suffix,\ |
|
237 |
prefix ## EBP ## suffix,\ |
|
238 |
prefix ## ESI ## suffix,\ |
|
239 |
prefix ## EDI ## suffix,\ |
|
240 |
prefix ## R8 ## suffix,\ |
|
241 |
prefix ## R9 ## suffix,\ |
|
242 |
prefix ## R10 ## suffix,\ |
|
243 |
prefix ## R11 ## suffix,\ |
|
244 |
prefix ## R12 ## suffix,\ |
|
245 |
prefix ## R13 ## suffix,\ |
|
246 |
prefix ## R14 ## suffix,\ |
|
247 |
prefix ## R15 ## suffix, |
|
248 |
|
|
249 | 242 |
#else /* !TARGET_X86_64 */ |
250 | 243 |
|
251 | 244 |
#define NB_OP_SIZES 3 |
252 | 245 |
|
253 |
#define DEF_REGS(prefix, suffix) \ |
|
254 |
prefix ## EAX ## suffix,\ |
|
255 |
prefix ## ECX ## suffix,\ |
|
256 |
prefix ## EDX ## suffix,\ |
|
257 |
prefix ## EBX ## suffix,\ |
|
258 |
prefix ## ESP ## suffix,\ |
|
259 |
prefix ## EBP ## suffix,\ |
|
260 |
prefix ## ESI ## suffix,\ |
|
261 |
prefix ## EDI ## suffix, |
|
262 |
|
|
263 | 246 |
#endif /* !TARGET_X86_64 */ |
264 | 247 |
|
265 | 248 |
#if defined(WORDS_BIGENDIAN) |
... | ... | |
510 | 493 |
} |
511 | 494 |
#endif |
512 | 495 |
|
513 |
static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = { |
|
514 |
[0] = { |
|
515 |
DEF_REGS(gen_op_cmovw_, _T1_T0) |
|
516 |
}, |
|
517 |
[1] = { |
|
518 |
DEF_REGS(gen_op_cmovl_, _T1_T0) |
|
519 |
}, |
|
520 |
#ifdef TARGET_X86_64 |
|
521 |
[2] = { |
|
522 |
DEF_REGS(gen_op_cmovq_, _T1_T0) |
|
523 |
}, |
|
524 |
#endif |
|
525 |
}; |
|
526 |
|
|
527 | 496 |
static inline void gen_op_lds_T0_A0(int idx) |
528 | 497 |
{ |
529 | 498 |
int mem_index = (idx >> 2) - 1; |
... | ... | |
743 | 712 |
tcg_gen_brcond_tl(TCG_COND_EQ, cpu_tmp0, tcg_const_tl(0), label1); |
744 | 713 |
} |
745 | 714 |
|
746 |
static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = { |
|
747 |
{ |
|
748 |
gen_op_jnz_subb, |
|
749 |
gen_op_jnz_subw, |
|
750 |
gen_op_jnz_subl, |
|
751 |
X86_64_ONLY(gen_op_jnz_subq), |
|
752 |
}, |
|
753 |
{ |
|
754 |
gen_op_jz_subb, |
|
755 |
gen_op_jz_subw, |
|
756 |
gen_op_jz_subl, |
|
757 |
X86_64_ONLY(gen_op_jz_subq), |
|
758 |
}, |
|
759 |
}; |
|
760 |
|
|
761 | 715 |
static void *helper_in_func[3] = { |
762 | 716 |
helper_inb, |
763 | 717 |
helper_inw, |
... | ... | |
858 | 812 |
tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
859 | 813 |
} |
860 | 814 |
|
815 |
/* compute eflags.C to reg */ |
|
816 |
static void gen_compute_eflags_c(TCGv reg) |
|
817 |
{ |
|
818 |
#if TCG_TARGET_REG_BITS == 32 |
|
819 |
tcg_gen_shli_i32(cpu_tmp2_i32, cpu_cc_op, 3); |
|
820 |
tcg_gen_addi_i32(cpu_tmp2_i32, cpu_tmp2_i32, |
|
821 |
(long)cc_table + offsetof(CCTable, compute_c)); |
|
822 |
tcg_gen_ld_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0); |
|
823 |
tcg_gen_call(&tcg_ctx, cpu_tmp2_i32, TCG_CALL_PURE, |
|
824 |
1, &cpu_tmp2_i32, 0, NULL); |
|
825 |
#else |
|
826 |
tcg_gen_extu_i32_tl(cpu_tmp1_i64, cpu_cc_op); |
|
827 |
tcg_gen_shli_i64(cpu_tmp1_i64, cpu_tmp1_i64, 4); |
|
828 |
tcg_gen_addi_i64(cpu_tmp1_i64, cpu_tmp1_i64, |
|
829 |
(long)cc_table + offsetof(CCTable, compute_c)); |
|
830 |
tcg_gen_ld_i64(cpu_tmp1_i64, cpu_tmp1_i64, 0); |
|
831 |
tcg_gen_call(&tcg_ctx, cpu_tmp1_i64, TCG_CALL_PURE, |
|
832 |
1, &cpu_tmp2_i32, 0, NULL); |
|
833 |
#endif |
|
834 |
tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); |
|
835 |
} |
|
836 |
|
|
837 |
/* compute all eflags to cc_src */ |
|
838 |
static void gen_compute_eflags(TCGv reg) |
|
839 |
{ |
|
840 |
#if TCG_TARGET_REG_BITS == 32 |
|
841 |
tcg_gen_shli_i32(cpu_tmp2_i32, cpu_cc_op, 3); |
|
842 |
tcg_gen_addi_i32(cpu_tmp2_i32, cpu_tmp2_i32, |
|
843 |
(long)cc_table + offsetof(CCTable, compute_all)); |
|
844 |
tcg_gen_ld_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0); |
|
845 |
tcg_gen_call(&tcg_ctx, cpu_tmp2_i32, TCG_CALL_PURE, |
|
846 |
1, &cpu_tmp2_i32, 0, NULL); |
|
847 |
#else |
|
848 |
tcg_gen_extu_i32_tl(cpu_tmp1_i64, cpu_cc_op); |
|
849 |
tcg_gen_shli_i64(cpu_tmp1_i64, cpu_tmp1_i64, 4); |
|
850 |
tcg_gen_addi_i64(cpu_tmp1_i64, cpu_tmp1_i64, |
|
851 |
(long)cc_table + offsetof(CCTable, compute_all)); |
|
852 |
tcg_gen_ld_i64(cpu_tmp1_i64, cpu_tmp1_i64, 0); |
|
853 |
tcg_gen_call(&tcg_ctx, cpu_tmp1_i64, TCG_CALL_PURE, |
|
854 |
1, &cpu_tmp2_i32, 0, NULL); |
|
855 |
#endif |
|
856 |
tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); |
|
857 |
} |
|
858 |
|
|
859 |
static inline void gen_setcc_slow_T0(int op) |
|
860 |
{ |
|
861 |
switch(op) { |
|
862 |
case JCC_O: |
|
863 |
gen_compute_eflags(cpu_T[0]); |
|
864 |
tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 11); |
|
865 |
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
866 |
break; |
|
867 |
case JCC_B: |
|
868 |
gen_compute_eflags_c(cpu_T[0]); |
|
869 |
break; |
|
870 |
case JCC_Z: |
|
871 |
gen_compute_eflags(cpu_T[0]); |
|
872 |
tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 6); |
|
873 |
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
874 |
break; |
|
875 |
case JCC_BE: |
|
876 |
gen_compute_eflags(cpu_tmp0); |
|
877 |
tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 6); |
|
878 |
tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0); |
|
879 |
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
880 |
break; |
|
881 |
case JCC_S: |
|
882 |
gen_compute_eflags(cpu_T[0]); |
|
883 |
tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 7); |
|
884 |
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
885 |
break; |
|
886 |
case JCC_P: |
|
887 |
gen_compute_eflags(cpu_T[0]); |
|
888 |
tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 2); |
|
889 |
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
890 |
break; |
|
891 |
case JCC_L: |
|
892 |
gen_compute_eflags(cpu_tmp0); |
|
893 |
tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 11); /* CC_O */ |
|
894 |
tcg_gen_shri_tl(cpu_tmp0, cpu_tmp0, 7); /* CC_S */ |
|
895 |
tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0); |
|
896 |
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
897 |
break; |
|
898 |
default: |
|
899 |
case JCC_LE: |
|
900 |
gen_compute_eflags(cpu_tmp0); |
|
901 |
tcg_gen_shri_tl(cpu_T[0], cpu_tmp0, 11); /* CC_O */ |
|
902 |
tcg_gen_shri_tl(cpu_tmp4, cpu_tmp0, 7); /* CC_S */ |
|
903 |
tcg_gen_shri_tl(cpu_tmp0, cpu_tmp0, 6); /* CC_Z */ |
|
904 |
tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp4); |
|
905 |
tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0); |
|
906 |
tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 1); |
|
907 |
break; |
|
908 |
} |
|
909 |
} |
|
910 |
|
|
911 |
/* return true if setcc_slow is not needed (WARNING: must be kept in |
|
912 |
sync with gen_jcc1) */ |
|
913 |
static int is_fast_jcc_case(DisasContext *s, int b) |
|
914 |
{ |
|
915 |
int jcc_op; |
|
916 |
jcc_op = (b >> 1) & 7; |
|
917 |
switch(s->cc_op) { |
|
918 |
/* we optimize the cmp/jcc case */ |
|
919 |
case CC_OP_SUBB: |
|
920 |
case CC_OP_SUBW: |
|
921 |
case CC_OP_SUBL: |
|
922 |
case CC_OP_SUBQ: |
|
923 |
if (jcc_op == JCC_O || jcc_op == JCC_P) |
|
924 |
goto slow_jcc; |
|
925 |
break; |
|
926 |
|
|
927 |
/* some jumps are easy to compute */ |
|
928 |
case CC_OP_ADDB: |
|
929 |
case CC_OP_ADDW: |
|
930 |
case CC_OP_ADDL: |
|
931 |
case CC_OP_ADDQ: |
|
932 |
|
|
933 |
case CC_OP_LOGICB: |
|
934 |
case CC_OP_LOGICW: |
|
935 |
case CC_OP_LOGICL: |
|
936 |
case CC_OP_LOGICQ: |
|
937 |
|
|
938 |
case CC_OP_INCB: |
|
939 |
case CC_OP_INCW: |
|
940 |
case CC_OP_INCL: |
|
941 |
case CC_OP_INCQ: |
|
942 |
|
|
943 |
case CC_OP_DECB: |
|
944 |
case CC_OP_DECW: |
|
945 |
case CC_OP_DECL: |
|
946 |
case CC_OP_DECQ: |
|
947 |
|
|
948 |
case CC_OP_SHLB: |
|
949 |
case CC_OP_SHLW: |
|
950 |
case CC_OP_SHLL: |
|
951 |
case CC_OP_SHLQ: |
|
952 |
if (jcc_op != JCC_Z && jcc_op != JCC_S) |
|
953 |
goto slow_jcc; |
|
954 |
break; |
|
955 |
default: |
|
956 |
slow_jcc: |
|
957 |
return 0; |
|
958 |
} |
|
959 |
return 1; |
|
960 |
} |
|
961 |
|
|
962 |
/* generate a conditional jump to label 'l1' according to jump opcode |
|
963 |
value 'b'. In the fast case, T0 is guaranted not to be used. */ |
|
964 |
static inline void gen_jcc1(DisasContext *s, int cc_op, int b, int l1) |
|
965 |
{ |
|
966 |
int inv, jcc_op, size, cond; |
|
967 |
TCGv t0; |
|
968 |
|
|
969 |
inv = b & 1; |
|
970 |
jcc_op = (b >> 1) & 7; |
|
971 |
|
|
972 |
switch(cc_op) { |
|
973 |
/* we optimize the cmp/jcc case */ |
|
974 |
case CC_OP_SUBB: |
|
975 |
case CC_OP_SUBW: |
|
976 |
case CC_OP_SUBL: |
|
977 |
case CC_OP_SUBQ: |
|
978 |
|
|
979 |
size = cc_op - CC_OP_SUBB; |
|
980 |
switch(jcc_op) { |
|
981 |
case JCC_Z: |
|
982 |
fast_jcc_z: |
|
983 |
switch(size) { |
|
984 |
case 0: |
|
985 |
tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xff); |
|
986 |
t0 = cpu_tmp0; |
|
987 |
break; |
|
988 |
case 1: |
|
989 |
tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xffff); |
|
990 |
t0 = cpu_tmp0; |
|
991 |
break; |
|
992 |
#ifdef TARGET_X86_64 |
|
993 |
case 2: |
|
994 |
tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0xffffffff); |
|
995 |
t0 = cpu_tmp0; |
|
996 |
break; |
|
997 |
#endif |
|
998 |
default: |
|
999 |
t0 = cpu_cc_dst; |
|
1000 |
break; |
|
1001 |
} |
|
1002 |
tcg_gen_brcond_tl(inv ? TCG_COND_NE : TCG_COND_EQ, t0, |
|
1003 |
tcg_const_tl(0), l1); |
|
1004 |
break; |
|
1005 |
case JCC_S: |
|
1006 |
fast_jcc_s: |
|
1007 |
switch(size) { |
|
1008 |
case 0: |
|
1009 |
tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x80); |
|
1010 |
tcg_gen_brcond_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0, |
|
1011 |
tcg_const_tl(0), l1); |
|
1012 |
break; |
|
1013 |
case 1: |
|
1014 |
tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x8000); |
|
1015 |
tcg_gen_brcond_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0, |
|
1016 |
tcg_const_tl(0), l1); |
|
1017 |
break; |
|
1018 |
#ifdef TARGET_X86_64 |
|
1019 |
case 2: |
|
1020 |
tcg_gen_andi_tl(cpu_tmp0, cpu_cc_dst, 0x80000000); |
|
1021 |
tcg_gen_brcond_tl(inv ? TCG_COND_EQ : TCG_COND_NE, cpu_tmp0, |
|
1022 |
tcg_const_tl(0), l1); |
|
1023 |
break; |
|
1024 |
#endif |
|
1025 |
default: |
|
1026 |
tcg_gen_brcond_tl(inv ? TCG_COND_GE : TCG_COND_LT, cpu_cc_dst, |
|
1027 |
tcg_const_tl(0), l1); |
|
1028 |
break; |
|
1029 |
} |
|
1030 |
break; |
|
1031 |
|
|
1032 |
case JCC_B: |
|
1033 |
cond = inv ? TCG_COND_GEU : TCG_COND_LTU; |
|
1034 |
goto fast_jcc_b; |
|
1035 |
case JCC_BE: |
|
1036 |
cond = inv ? TCG_COND_GTU : TCG_COND_LEU; |
|
1037 |
fast_jcc_b: |
|
1038 |
tcg_gen_add_tl(cpu_tmp4, cpu_cc_dst, cpu_cc_src); |
|
1039 |
switch(size) { |
|
1040 |
case 0: |
|
1041 |
t0 = cpu_tmp0; |
|
1042 |
tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xff); |
|
1043 |
tcg_gen_andi_tl(t0, cpu_cc_src, 0xff); |
|
1044 |
break; |
|
1045 |
case 1: |
|
1046 |
t0 = cpu_tmp0; |
|
1047 |
tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xffff); |
|
1048 |
tcg_gen_andi_tl(t0, cpu_cc_src, 0xffff); |
|
1049 |
break; |
|
1050 |
#ifdef TARGET_X86_64 |
|
1051 |
case 2: |
|
1052 |
t0 = cpu_tmp0; |
|
1053 |
tcg_gen_andi_tl(cpu_tmp4, cpu_tmp4, 0xffffffff); |
|
1054 |
tcg_gen_andi_tl(t0, cpu_cc_src, 0xffffffff); |
|
1055 |
break; |
|
1056 |
#endif |
|
1057 |
default: |
|
1058 |
t0 = cpu_cc_src; |
|
1059 |
break; |
|
1060 |
} |
|
1061 |
tcg_gen_brcond_tl(cond, cpu_tmp4, t0, l1); |
|
1062 |
break; |
|
1063 |
|
|
1064 |
case JCC_L: |
|
1065 |
cond = inv ? TCG_COND_GE : TCG_COND_LT; |
|
1066 |
goto fast_jcc_l; |
|
1067 |
case JCC_LE: |
|
1068 |
cond = inv ? TCG_COND_GT : TCG_COND_LE; |
|
1069 |
fast_jcc_l: |
|
1070 |
tcg_gen_add_tl(cpu_tmp4, cpu_cc_dst, cpu_cc_src); |
|
1071 |
switch(size) { |
|
1072 |
case 0: |
|
1073 |
t0 = cpu_tmp0; |
|
1074 |
tcg_gen_ext8s_tl(cpu_tmp4, cpu_tmp4); |
|
1075 |
tcg_gen_ext8s_tl(t0, cpu_cc_src); |
|
1076 |
break; |
|
1077 |
case 1: |
|
1078 |
t0 = cpu_tmp0; |
|
1079 |
tcg_gen_ext16s_tl(cpu_tmp4, cpu_tmp4); |
|
1080 |
tcg_gen_ext16s_tl(t0, cpu_cc_src); |
|
1081 |
break; |
|
1082 |
#ifdef TARGET_X86_64 |
|
1083 |
case 2: |
|
1084 |
t0 = cpu_tmp0; |
|
1085 |
tcg_gen_ext32s_tl(cpu_tmp4, cpu_tmp4); |
|
1086 |
tcg_gen_ext32s_tl(t0, cpu_cc_src); |
|
1087 |
break; |
|
1088 |
#endif |
|
1089 |
default: |
|
1090 |
t0 = cpu_cc_src; |
|
1091 |
break; |
|
1092 |
} |
|
1093 |
tcg_gen_brcond_tl(cond, cpu_tmp4, t0, l1); |
|
1094 |
break; |
|
1095 |
|
|
1096 |
default: |
|
1097 |
goto slow_jcc; |
|
1098 |
} |
|
1099 |
break; |
|
1100 |
|
|
1101 |
/* some jumps are easy to compute */ |
|
1102 |
case CC_OP_ADDB: |
|
1103 |
case CC_OP_ADDW: |
|
1104 |
case CC_OP_ADDL: |
|
1105 |
case CC_OP_ADDQ: |
|
1106 |
|
|
1107 |
case CC_OP_ADCB: |
|
1108 |
case CC_OP_ADCW: |
|
1109 |
case CC_OP_ADCL: |
|
1110 |
case CC_OP_ADCQ: |
|
1111 |
|
|
1112 |
case CC_OP_SBBB: |
|
1113 |
case CC_OP_SBBW: |
|
1114 |
case CC_OP_SBBL: |
|
1115 |
case CC_OP_SBBQ: |
|
1116 |
|
|
1117 |
case CC_OP_LOGICB: |
|
1118 |
case CC_OP_LOGICW: |
|
1119 |
case CC_OP_LOGICL: |
|
1120 |
case CC_OP_LOGICQ: |
|
1121 |
|
|
1122 |
case CC_OP_INCB: |
|
1123 |
case CC_OP_INCW: |
|
1124 |
case CC_OP_INCL: |
|
1125 |
case CC_OP_INCQ: |
|
1126 |
|
|
1127 |
case CC_OP_DECB: |
|
1128 |
case CC_OP_DECW: |
|
1129 |
case CC_OP_DECL: |
|
1130 |
case CC_OP_DECQ: |
|
1131 |
|
|
1132 |
case CC_OP_SHLB: |
|
1133 |
case CC_OP_SHLW: |
|
1134 |
case CC_OP_SHLL: |
|
1135 |
case CC_OP_SHLQ: |
|
1136 |
|
|
1137 |
case CC_OP_SARB: |
|
1138 |
case CC_OP_SARW: |
|
1139 |
case CC_OP_SARL: |
|
1140 |
case CC_OP_SARQ: |
|
1141 |
switch(jcc_op) { |
|
1142 |
case JCC_Z: |
|
1143 |
size = (cc_op - CC_OP_ADDB) & 3; |
|
1144 |
goto fast_jcc_z; |
|
1145 |
case JCC_S: |
|
1146 |
size = (cc_op - CC_OP_ADDB) & 3; |
|
1147 |
goto fast_jcc_s; |
|
1148 |
default: |
|
1149 |
goto slow_jcc; |
|
1150 |
} |
|
1151 |
break; |
|
1152 |
default: |
|
1153 |
slow_jcc: |
|
1154 |
gen_setcc_slow_T0(jcc_op); |
|
1155 |
tcg_gen_brcond_tl(inv ? TCG_COND_EQ : TCG_COND_NE, |
|
1156 |
cpu_T[0], tcg_const_tl(0), l1); |
|
1157 |
break; |
|
1158 |
} |
|
1159 |
} |
|
1160 |
|
|
861 | 1161 |
/* XXX: does not work with gdbstub "ice" single step - not a |
862 | 1162 |
serious problem */ |
863 | 1163 |
static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip) |
... | ... | |
974 | 1274 |
gen_ ## op(s, ot); \ |
975 | 1275 |
gen_op_add_reg_im(s->aflag, R_ECX, -1); \ |
976 | 1276 |
gen_op_set_cc_op(CC_OP_SUBB + ot); \ |
977 |
gen_op_string_jnz_sub[nz][ot](l2);\
|
|
1277 |
gen_jcc1(s, CC_OP_SUBB + ot, (JCC_Z << 1) | (nz ^ 1), l2); \
|
|
978 | 1278 |
if (!s->jmp_opt) \ |
979 | 1279 |
gen_op_jz_ecx(s->aflag, l2); \ |
980 | 1280 |
gen_jmp(s, cur_eip); \ |
... | ... | |
988 | 1288 |
GEN_REPZ2(scas) |
989 | 1289 |
GEN_REPZ2(cmps) |
990 | 1290 |
|
991 |
enum { |
|
992 |
JCC_O, |
|
993 |
JCC_B, |
|
994 |
JCC_Z, |
|
995 |
JCC_BE, |
|
996 |
JCC_S, |
|
997 |
JCC_P, |
|
998 |
JCC_L, |
|
999 |
JCC_LE, |
|
1000 |
}; |
|
1001 |
|
|
1002 |
static GenOpFunc1 *gen_jcc_sub[4][8] = { |
|
1003 |
[OT_BYTE] = { |
|
1004 |
NULL, |
|
1005 |
gen_op_jb_subb, |
|
1006 |
gen_op_jz_subb, |
|
1007 |
gen_op_jbe_subb, |
|
1008 |
gen_op_js_subb, |
|
1009 |
NULL, |
|
1010 |
gen_op_jl_subb, |
|
1011 |
gen_op_jle_subb, |
|
1012 |
}, |
|
1013 |
[OT_WORD] = { |
|
1014 |
NULL, |
|
1015 |
gen_op_jb_subw, |
|
1016 |
gen_op_jz_subw, |
|
1017 |
gen_op_jbe_subw, |
|
1018 |
gen_op_js_subw, |
|
1019 |
NULL, |
|
1020 |
gen_op_jl_subw, |
|
1021 |
gen_op_jle_subw, |
|
1022 |
}, |
|
1023 |
[OT_LONG] = { |
|
1024 |
NULL, |
|
1025 |
gen_op_jb_subl, |
|
1026 |
gen_op_jz_subl, |
|
1027 |
gen_op_jbe_subl, |
|
1028 |
gen_op_js_subl, |
|
1029 |
NULL, |
|
1030 |
gen_op_jl_subl, |
|
1031 |
gen_op_jle_subl, |
|
1032 |
}, |
|
1033 |
#ifdef TARGET_X86_64 |
|
1034 |
[OT_QUAD] = { |
|
1035 |
NULL, |
|
1036 |
BUGGY_64(gen_op_jb_subq), |
|
1037 |
gen_op_jz_subq, |
|
1038 |
BUGGY_64(gen_op_jbe_subq), |
|
1039 |
gen_op_js_subq, |
|
1040 |
NULL, |
|
1041 |
BUGGY_64(gen_op_jl_subq), |
|
1042 |
BUGGY_64(gen_op_jle_subq), |
|
1043 |
}, |
|
1044 |
#endif |
|
1045 |
}; |
|
1046 |
|
|
1047 |
static GenOpFunc *gen_setcc_slow[8] = { |
|
1048 |
gen_op_seto_T0_cc, |
|
1049 |
gen_op_setb_T0_cc, |
|
1050 |
gen_op_setz_T0_cc, |
|
1051 |
gen_op_setbe_T0_cc, |
|
1052 |
gen_op_sets_T0_cc, |
|
1053 |
gen_op_setp_T0_cc, |
|
1054 |
gen_op_setl_T0_cc, |
|
1055 |
gen_op_setle_T0_cc, |
|
1056 |
}; |
|
1057 |
|
|
1058 |
static GenOpFunc *gen_setcc_sub[4][8] = { |
|
1059 |
[OT_BYTE] = { |
|
1060 |
NULL, |
|
1061 |
gen_op_setb_T0_subb, |
|
1062 |
gen_op_setz_T0_subb, |
|
1063 |
gen_op_setbe_T0_subb, |
|
1064 |
gen_op_sets_T0_subb, |
|
1065 |
NULL, |
|
1066 |
gen_op_setl_T0_subb, |
|
1067 |
gen_op_setle_T0_subb, |
|
1068 |
}, |
|
1069 |
[OT_WORD] = { |
|
1070 |
NULL, |
|
1071 |
gen_op_setb_T0_subw, |
|
1072 |
gen_op_setz_T0_subw, |
|
1073 |
gen_op_setbe_T0_subw, |
|
1074 |
gen_op_sets_T0_subw, |
|
1075 |
NULL, |
|
1076 |
gen_op_setl_T0_subw, |
|
1077 |
gen_op_setle_T0_subw, |
|
1078 |
}, |
|
1079 |
[OT_LONG] = { |
|
1080 |
NULL, |
|
1081 |
gen_op_setb_T0_subl, |
|
1082 |
gen_op_setz_T0_subl, |
|
1083 |
gen_op_setbe_T0_subl, |
|
1084 |
gen_op_sets_T0_subl, |
|
1085 |
NULL, |
|
1086 |
gen_op_setl_T0_subl, |
|
1087 |
gen_op_setle_T0_subl, |
|
1088 |
}, |
|
1089 |
#ifdef TARGET_X86_64 |
|
1090 |
[OT_QUAD] = { |
|
1091 |
NULL, |
|
1092 |
gen_op_setb_T0_subq, |
|
1093 |
gen_op_setz_T0_subq, |
|
1094 |
gen_op_setbe_T0_subq, |
|
1095 |
gen_op_sets_T0_subq, |
|
1096 |
NULL, |
|
1097 |
gen_op_setl_T0_subq, |
|
1098 |
gen_op_setle_T0_subq, |
|
1099 |
}, |
|
1100 |
#endif |
|
1101 |
}; |
|
1102 |
|
|
1103 | 1291 |
static void *helper_fp_arith_ST0_FT0[8] = { |
1104 | 1292 |
helper_fadd_ST0_FT0, |
1105 | 1293 |
helper_fmul_ST0_FT0, |
... | ... | |
1123 | 1311 |
helper_fdiv_STN_ST0, |
1124 | 1312 |
}; |
1125 | 1313 |
|
1126 |
/* compute eflags.C to reg */ |
|
1127 |
static void gen_compute_eflags_c(TCGv reg) |
|
1128 |
{ |
|
1129 |
#if TCG_TARGET_REG_BITS == 32 |
|
1130 |
tcg_gen_shli_i32(cpu_tmp2_i32, cpu_cc_op, 3); |
|
1131 |
tcg_gen_addi_i32(cpu_tmp2_i32, cpu_tmp2_i32, |
|
1132 |
(long)cc_table + offsetof(CCTable, compute_c)); |
|
1133 |
tcg_gen_ld_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0); |
|
1134 |
tcg_gen_call(&tcg_ctx, cpu_tmp2_i32, TCG_CALL_PURE, |
|
1135 |
1, &cpu_tmp2_i32, 0, NULL); |
|
1136 |
#else |
|
1137 |
tcg_gen_extu_i32_tl(cpu_tmp1_i64, cpu_cc_op); |
|
1138 |
tcg_gen_shli_i64(cpu_tmp1_i64, cpu_tmp1_i64, 4); |
|
1139 |
tcg_gen_addi_i64(cpu_tmp1_i64, cpu_tmp1_i64, |
|
1140 |
(long)cc_table + offsetof(CCTable, compute_c)); |
|
1141 |
tcg_gen_ld_i64(cpu_tmp1_i64, cpu_tmp1_i64, 0); |
|
1142 |
tcg_gen_call(&tcg_ctx, cpu_tmp1_i64, TCG_CALL_PURE, |
|
1143 |
1, &cpu_tmp2_i32, 0, NULL); |
|
1144 |
#endif |
|
1145 |
tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); |
|
1146 |
} |
|
1147 |
|
|
1148 |
/* compute all eflags to cc_src */ |
|
1149 |
static void gen_compute_eflags(TCGv reg) |
|
1150 |
{ |
|
1151 |
#if TCG_TARGET_REG_BITS == 32 |
|
1152 |
tcg_gen_shli_i32(cpu_tmp2_i32, cpu_cc_op, 3); |
|
1153 |
tcg_gen_addi_i32(cpu_tmp2_i32, cpu_tmp2_i32, |
|
1154 |
(long)cc_table + offsetof(CCTable, compute_all)); |
|
1155 |
tcg_gen_ld_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0); |
|
1156 |
tcg_gen_call(&tcg_ctx, cpu_tmp2_i32, TCG_CALL_PURE, |
|
1157 |
1, &cpu_tmp2_i32, 0, NULL); |
|
1158 |
#else |
|
1159 |
tcg_gen_extu_i32_tl(cpu_tmp1_i64, cpu_cc_op); |
|
1160 |
tcg_gen_shli_i64(cpu_tmp1_i64, cpu_tmp1_i64, 4); |
|
1161 |
tcg_gen_addi_i64(cpu_tmp1_i64, cpu_tmp1_i64, |
|
1162 |
(long)cc_table + offsetof(CCTable, compute_all)); |
|
1163 |
tcg_gen_ld_i64(cpu_tmp1_i64, cpu_tmp1_i64, 0); |
|
1164 |
tcg_gen_call(&tcg_ctx, cpu_tmp1_i64, TCG_CALL_PURE, |
|
1165 |
1, &cpu_tmp2_i32, 0, NULL); |
|
1166 |
#endif |
|
1167 |
tcg_gen_extu_i32_tl(reg, cpu_tmp2_i32); |
|
1168 |
} |
|
1169 |
|
|
1170 | 1314 |
/* if d == OR_TMP0, it means memory operand (address in A0) */ |
1171 | 1315 |
static void gen_op(DisasContext *s1, int op, int ot, int d) |
1172 | 1316 |
{ |
... | ... | |
1974 | 2118 |
static inline void gen_jcc(DisasContext *s, int b, |
1975 | 2119 |
target_ulong val, target_ulong next_eip) |
1976 | 2120 |
{ |
1977 |
TranslationBlock *tb; |
|
1978 |
int inv, jcc_op; |
|
1979 |
GenOpFunc1 *func; |
|
1980 |
target_ulong tmp; |
|
1981 |
int l1, l2; |
|
1982 |
|
|
1983 |
inv = b & 1; |
|
1984 |
jcc_op = (b >> 1) & 7; |
|
2121 |
int l1, l2, cc_op; |
|
1985 | 2122 |
|
2123 |
cc_op = s->cc_op; |
|
2124 |
if (s->cc_op != CC_OP_DYNAMIC) { |
|
2125 |
gen_op_set_cc_op(s->cc_op); |
|
2126 |
s->cc_op = CC_OP_DYNAMIC; |
|
2127 |
} |
|
1986 | 2128 |
if (s->jmp_opt) { |
1987 |
switch(s->cc_op) { |
|
1988 |
/* we optimize the cmp/jcc case */ |
|
1989 |
case CC_OP_SUBB: |
|
1990 |
case CC_OP_SUBW: |
|
1991 |
case CC_OP_SUBL: |
|
1992 |
case CC_OP_SUBQ: |
|
1993 |
func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op]; |
|
1994 |
break; |
|
1995 |
|
|
1996 |
/* some jumps are easy to compute */ |
|
1997 |
case CC_OP_ADDB: |
|
1998 |
case CC_OP_ADDW: |
|
1999 |
case CC_OP_ADDL: |
|
2000 |
case CC_OP_ADDQ: |
|
2001 |
|
|
2002 |
case CC_OP_ADCB: |
|
2003 |
case CC_OP_ADCW: |
|
2004 |
case CC_OP_ADCL: |
|
2005 |
case CC_OP_ADCQ: |
|
2006 |
|
|
2007 |
case CC_OP_SBBB: |
|
2008 |
case CC_OP_SBBW: |
|
2009 |
case CC_OP_SBBL: |
|
2010 |
case CC_OP_SBBQ: |
|
2011 |
|
|
2012 |
case CC_OP_LOGICB: |
|
2013 |
case CC_OP_LOGICW: |
|
2014 |
case CC_OP_LOGICL: |
|
2015 |
case CC_OP_LOGICQ: |
|
2016 |
|
|
2017 |
case CC_OP_INCB: |
|
2018 |
case CC_OP_INCW: |
|
2019 |
case CC_OP_INCL: |
|
2020 |
case CC_OP_INCQ: |
|
2021 |
|
|
2022 |
case CC_OP_DECB: |
|
2023 |
case CC_OP_DECW: |
|
2024 |
case CC_OP_DECL: |
|
2025 |
case CC_OP_DECQ: |
|
2026 |
|
|
2027 |
case CC_OP_SHLB: |
|
2028 |
case CC_OP_SHLW: |
|
2029 |
case CC_OP_SHLL: |
|
2030 |
case CC_OP_SHLQ: |
|
2031 |
|
|
2032 |
case CC_OP_SARB: |
|
2033 |
case CC_OP_SARW: |
|
2034 |
case CC_OP_SARL: |
|
2035 |
case CC_OP_SARQ: |
|
2036 |
switch(jcc_op) { |
|
2037 |
case JCC_Z: |
|
2038 |
func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op]; |
|
2039 |
break; |
|
2040 |
case JCC_S: |
|
2041 |
func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op]; |
|
2042 |
break; |
|
2043 |
default: |
|
2044 |
func = NULL; |
|
2045 |
break; |
|
2046 |
} |
|
2047 |
break; |
|
2048 |
default: |
|
2049 |
func = NULL; |
|
2050 |
break; |
|
2051 |
} |
|
2052 |
|
|
2053 |
if (s->cc_op != CC_OP_DYNAMIC) { |
|
2054 |
gen_op_set_cc_op(s->cc_op); |
|
2055 |
s->cc_op = CC_OP_DYNAMIC; |
|
2056 |
} |
|
2057 |
|
|
2058 |
if (!func) { |
|
2059 |
gen_setcc_slow[jcc_op](); |
|
2060 |
func = gen_op_jnz_T0_label; |
|
2061 |
} |
|
2062 |
|
|
2063 |
if (inv) { |
|
2064 |
tmp = val; |
|
2065 |
val = next_eip; |
|
2066 |
next_eip = tmp; |
|
2067 |
} |
|
2068 |
tb = s->tb; |
|
2069 |
|
|
2070 | 2129 |
l1 = gen_new_label(); |
2071 |
func(l1);
|
|
2072 |
|
|
2130 |
gen_jcc1(s, cc_op, b, l1);
|
|
2131 |
|
|
2073 | 2132 |
gen_goto_tb(s, 0, next_eip); |
2074 | 2133 |
|
2075 | 2134 |
gen_set_label(l1); |
2076 | 2135 |
gen_goto_tb(s, 1, val); |
2077 |
|
|
2078 | 2136 |
s->is_jmp = 3; |
2079 | 2137 |
} else { |
2080 | 2138 |
|
2081 |
if (s->cc_op != CC_OP_DYNAMIC) { |
|
2082 |
gen_op_set_cc_op(s->cc_op); |
|
2083 |
s->cc_op = CC_OP_DYNAMIC; |
|
2084 |
} |
|
2085 |
gen_setcc_slow[jcc_op](); |
|
2086 |
if (inv) { |
|
2087 |
tmp = val; |
|
2088 |
val = next_eip; |
|
2089 |
next_eip = tmp; |
|
2090 |
} |
|
2091 | 2139 |
l1 = gen_new_label(); |
2092 | 2140 |
l2 = gen_new_label(); |
2093 |
gen_op_jnz_T0_label(l1); |
|
2141 |
gen_jcc1(s, cc_op, b, l1); |
|
2142 |
|
|
2094 | 2143 |
gen_jmp_im(next_eip); |
2095 |
gen_op_jmp_label(l2); |
|
2144 |
tcg_gen_br(l2); |
|
2145 |
|
|
2096 | 2146 |
gen_set_label(l1); |
2097 | 2147 |
gen_jmp_im(val); |
2098 | 2148 |
gen_set_label(l2); |
... | ... | |
2102 | 2152 |
|
2103 | 2153 |
static void gen_setcc(DisasContext *s, int b) |
2104 | 2154 |
{ |
2105 |
int inv, jcc_op; |
|
2106 |
GenOpFunc *func; |
|
2107 |
|
|
2108 |
inv = b & 1; |
|
2109 |
jcc_op = (b >> 1) & 7; |
|
2110 |
switch(s->cc_op) { |
|
2111 |
/* we optimize the cmp/jcc case */ |
|
2112 |
case CC_OP_SUBB: |
|
2113 |
case CC_OP_SUBW: |
|
2114 |
case CC_OP_SUBL: |
|
2115 |
case CC_OP_SUBQ: |
|
2116 |
func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op]; |
|
2117 |
if (!func) |
|
2118 |
goto slow_jcc; |
|
2119 |
break; |
|
2120 |
|
|
2121 |
/* some jumps are easy to compute */ |
|
2122 |
case CC_OP_ADDB: |
|
2123 |
case CC_OP_ADDW: |
|
2124 |
case CC_OP_ADDL: |
|
2125 |
case CC_OP_ADDQ: |
|
2126 |
|
|
2127 |
case CC_OP_LOGICB: |
|
2128 |
case CC_OP_LOGICW: |
|
2129 |
case CC_OP_LOGICL: |
|
2130 |
case CC_OP_LOGICQ: |
|
2131 |
|
|
2132 |
case CC_OP_INCB: |
|
2133 |
case CC_OP_INCW: |
|
2134 |
case CC_OP_INCL: |
|
2135 |
case CC_OP_INCQ: |
|
2136 |
|
|
2137 |
case CC_OP_DECB: |
|
2138 |
case CC_OP_DECW: |
|
2139 |
case CC_OP_DECL: |
|
2140 |
case CC_OP_DECQ: |
|
2155 |
int inv, jcc_op, l1; |
|
2141 | 2156 |
|
2142 |
case CC_OP_SHLB: |
|
2143 |
case CC_OP_SHLW: |
|
2144 |
case CC_OP_SHLL: |
|
2145 |
case CC_OP_SHLQ: |
|
2146 |
switch(jcc_op) { |
|
2147 |
case JCC_Z: |
|
2148 |
func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op]; |
|
2149 |
break; |
|
2150 |
case JCC_S: |
|
2151 |
func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op]; |
|
2152 |
break; |
|
2153 |
default: |
|
2154 |
goto slow_jcc; |
|
2155 |
} |
|
2156 |
break; |
|
2157 |
default: |
|
2158 |
slow_jcc: |
|
2157 |
if (is_fast_jcc_case(s, b)) { |
|
2158 |
/* nominal case: we use a jump */ |
|
2159 |
tcg_gen_movi_tl(cpu_T[0], 0); |
|
2160 |
l1 = gen_new_label(); |
|
2161 |
gen_jcc1(s, s->cc_op, b ^ 1, l1); |
|
2162 |
tcg_gen_movi_tl(cpu_T[0], 1); |
|
2163 |
gen_set_label(l1); |
|
2164 |
} else { |
|
2165 |
/* slow case: it is more efficient not to generate a jump, |
|
2166 |
although it is questionnable whether this optimization is |
|
2167 |
worth to */ |
|
2168 |
inv = b & 1; |
|
2169 |
jcc_op = (b >> 1) & 7; |
|
2159 | 2170 |
if (s->cc_op != CC_OP_DYNAMIC) |
2160 | 2171 |
gen_op_set_cc_op(s->cc_op); |
2161 |
func = gen_setcc_slow[jcc_op]; |
|
2162 |
break; |
|
2163 |
} |
|
2164 |
func(); |
|
2165 |
if (inv) { |
|
2166 |
gen_op_xor_T0_1(); |
|
2172 |
gen_setcc_slow_T0(jcc_op); |
|
2173 |
if (inv) { |
|
2174 |
tcg_gen_xori_tl(cpu_T[0], cpu_T[0], 1); |
|
2175 |
} |
|
2167 | 2176 |
} |
2168 | 2177 |
} |
2169 | 2178 |
|
... | ... | |
5708 | 5717 |
gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); |
5709 | 5718 |
break; |
5710 | 5719 |
case 0x140 ... 0x14f: /* cmov Gv, Ev */ |
5711 |
ot = dflag + OT_WORD; |
|
5712 |
modrm = ldub_code(s->pc++); |
|
5713 |
reg = ((modrm >> 3) & 7) | rex_r; |
|
5714 |
mod = (modrm >> 6) & 3; |
|
5715 |
gen_setcc(s, b); |
|
5716 |
if (mod != 3) { |
|
5717 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
5718 |
gen_op_ld_T1_A0(ot + s->mem_index); |
|
5719 |
} else { |
|
5720 |
rm = (modrm & 7) | REX_B(s); |
|
5721 |
gen_op_mov_TN_reg(ot, 1, rm); |
|
5720 |
{ |
|
5721 |
int l1; |
|
5722 |
ot = dflag + OT_WORD; |
|
5723 |
modrm = ldub_code(s->pc++); |
|
5724 |
reg = ((modrm >> 3) & 7) | rex_r; |
|
5725 |
mod = (modrm >> 6) & 3; |
|
5726 |
if (mod != 3) { |
|
5727 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
5728 |
gen_op_ld_T1_A0(ot + s->mem_index); |
|
5729 |
} else { |
|
5730 |
rm = (modrm & 7) | REX_B(s); |
|
5731 |
gen_op_mov_TN_reg(ot, 1, rm); |
|
5732 |
} |
|
5733 |
if (s->cc_op != CC_OP_DYNAMIC) |
|
5734 |
gen_op_set_cc_op(s->cc_op); |
|
5735 |
#ifdef TARGET_X86_64 |
|
5736 |
if (ot == OT_LONG) { |
|
5737 |
/* XXX: specific Intel behaviour ? */ |
|
5738 |
l1 = gen_new_label(); |
|
5739 |
gen_jcc1(s, s->cc_op, b ^ 1, l1); |
|
5740 |
tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); |
|
5741 |
gen_set_label(l1); |
|
5742 |
tcg_gen_movi_tl(cpu_tmp0, 0); |
|
5743 |
tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET); |
|
5744 |
} else |
|
5745 |
#endif |
|
5746 |
{ |
|
5747 |
l1 = gen_new_label(); |
|
5748 |
gen_jcc1(s, s->cc_op, b ^ 1, l1); |
|
5749 |
gen_op_mov_reg_T1(ot, reg); |
|
5750 |
gen_set_label(l1); |
|
5751 |
} |
|
5722 | 5752 |
} |
5723 |
gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg](); |
|
5724 | 5753 |
break; |
5725 | 5754 |
|
5726 | 5755 |
/************************/ |
... | ... | |
6191 | 6220 |
|
6192 | 6221 |
gen_set_label(l3); |
6193 | 6222 |
gen_jmp_im(next_eip); |
6194 |
gen_op_jmp_label(l2);
|
|
6223 |
tcg_gen_br(l2);
|
|
6195 | 6224 |
|
6196 | 6225 |
gen_set_label(l1); |
6197 | 6226 |
gen_jmp_im(tval); |
Also available in: Unified diff