Commit a4a0ffdb2be25b381df38758b1b0a32ae04491d0
1 parent
0ea00c9a
added cmpxchg8b, cpuid, bound, eflags support, vm86 mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@53 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
108 additions
and
9 deletions
op-i386.c
@@ -607,11 +607,49 @@ void OPPROTO op_into(void) | @@ -607,11 +607,49 @@ void OPPROTO op_into(void) | ||
607 | int eflags; | 607 | int eflags; |
608 | eflags = cc_table[CC_OP].compute_all(); | 608 | eflags = cc_table[CC_OP].compute_all(); |
609 | if (eflags & CC_O) { | 609 | if (eflags & CC_O) { |
610 | - EIP = PARAM1; | ||
611 | raise_exception(EXCP04_INTO); | 610 | raise_exception(EXCP04_INTO); |
611 | + } | ||
612 | +} | ||
613 | + | ||
614 | +void OPPROTO op_boundw(void) | ||
615 | +{ | ||
616 | + int low, high, v; | ||
617 | + low = ldsw((uint8_t *)A0); | ||
618 | + high = ldsw((uint8_t *)A0 + 2); | ||
619 | + v = (int16_t)T0; | ||
620 | + if (v < low || v > high) | ||
621 | + raise_exception(EXCP05_BOUND); | ||
622 | + FORCE_RET(); | ||
623 | +} | ||
624 | + | ||
625 | +void OPPROTO op_boundl(void) | ||
626 | +{ | ||
627 | + int low, high, v; | ||
628 | + low = ldl((uint8_t *)A0); | ||
629 | + high = ldl((uint8_t *)A0 + 4); | ||
630 | + v = T0; | ||
631 | + if (v < low || v > high) | ||
632 | + raise_exception(EXCP05_BOUND); | ||
633 | + FORCE_RET(); | ||
634 | +} | ||
635 | + | ||
636 | +void OPPROTO op_cmpxchg8b(void) | ||
637 | +{ | ||
638 | + uint64_t d; | ||
639 | + int eflags; | ||
640 | + | ||
641 | + eflags = cc_table[CC_OP].compute_all(); | ||
642 | + d = ldq((uint8_t *)A0); | ||
643 | + if (d == (((uint64_t)EDX << 32) | EAX)) { | ||
644 | + stq((uint8_t *)A0, ((uint64_t)ECX << 32) | EBX); | ||
645 | + eflags |= CC_Z; | ||
612 | } else { | 646 | } else { |
613 | - EIP = PARAM2; | 647 | + EDX = d >> 32; |
648 | + EAX = d; | ||
649 | + eflags &= ~CC_Z; | ||
614 | } | 650 | } |
651 | + CC_SRC = eflags; | ||
652 | + FORCE_RET(); | ||
615 | } | 653 | } |
616 | 654 | ||
617 | /* string ops */ | 655 | /* string ops */ |
@@ -793,7 +831,8 @@ void op_addw_ESP_im(void) | @@ -793,7 +831,8 @@ void op_addw_ESP_im(void) | ||
793 | #ifndef __i386__ | 831 | #ifndef __i386__ |
794 | uint64_t emu_time; | 832 | uint64_t emu_time; |
795 | #endif | 833 | #endif |
796 | -void op_rdtsc(void) | 834 | + |
835 | +void OPPROTO op_rdtsc(void) | ||
797 | { | 836 | { |
798 | uint64_t val; | 837 | uint64_t val; |
799 | #ifdef __i386__ | 838 | #ifdef __i386__ |
@@ -806,6 +845,51 @@ void op_rdtsc(void) | @@ -806,6 +845,51 @@ void op_rdtsc(void) | ||
806 | EDX = val >> 32; | 845 | EDX = val >> 32; |
807 | } | 846 | } |
808 | 847 | ||
848 | +/* We simulate a pre-MMX pentium as in valgrind */ | ||
849 | +#define CPUID_FP87 (1 << 0) | ||
850 | +#define CPUID_VME (1 << 1) | ||
851 | +#define CPUID_DE (1 << 2) | ||
852 | +#define CPUID_PSE (1 << 3) | ||
853 | +#define CPUID_TSC (1 << 4) | ||
854 | +#define CPUID_MSR (1 << 5) | ||
855 | +#define CPUID_PAE (1 << 6) | ||
856 | +#define CPUID_MCE (1 << 7) | ||
857 | +#define CPUID_CX8 (1 << 8) | ||
858 | +#define CPUID_APIC (1 << 9) | ||
859 | +#define CPUID_SEP (1 << 11) /* sysenter/sysexit */ | ||
860 | +#define CPUID_MTRR (1 << 12) | ||
861 | +#define CPUID_PGE (1 << 13) | ||
862 | +#define CPUID_MCA (1 << 14) | ||
863 | +#define CPUID_CMOV (1 << 15) | ||
864 | +/* ... */ | ||
865 | +#define CPUID_MMX (1 << 23) | ||
866 | +#define CPUID_FXSR (1 << 24) | ||
867 | +#define CPUID_SSE (1 << 25) | ||
868 | +#define CPUID_SSE2 (1 << 26) | ||
869 | + | ||
870 | +void helper_cpuid(void) | ||
871 | +{ | ||
872 | + if (EAX == 0) { | ||
873 | + EAX = 1; /* max EAX index supported */ | ||
874 | + EBX = 0x756e6547; | ||
875 | + ECX = 0x6c65746e; | ||
876 | + EDX = 0x49656e69; | ||
877 | + } else { | ||
878 | + /* EAX = 1 info */ | ||
879 | + EAX = 0x52b; | ||
880 | + EBX = 0; | ||
881 | + ECX = 0; | ||
882 | + EDX = CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | | ||
883 | + CPUID_TSC | CPUID_MSR | CPUID_MCE | | ||
884 | + CPUID_CX8; | ||
885 | + } | ||
886 | +} | ||
887 | + | ||
888 | +void OPPROTO op_cpuid(void) | ||
889 | +{ | ||
890 | + helper_cpuid(); | ||
891 | +} | ||
892 | + | ||
809 | /* bcd */ | 893 | /* bcd */ |
810 | 894 | ||
811 | /* XXX: exception */ | 895 | /* XXX: exception */ |
@@ -938,6 +1022,7 @@ void OPPROTO op_das(void) | @@ -938,6 +1022,7 @@ void OPPROTO op_das(void) | ||
938 | 1022 | ||
939 | /* segment handling */ | 1023 | /* segment handling */ |
940 | 1024 | ||
1025 | +/* XXX: use static VM86 information */ | ||
941 | void load_seg(int seg_reg, int selector) | 1026 | void load_seg(int seg_reg, int selector) |
942 | { | 1027 | { |
943 | SegmentCache *sc; | 1028 | SegmentCache *sc; |
@@ -948,7 +1033,7 @@ void load_seg(int seg_reg, int selector) | @@ -948,7 +1033,7 @@ void load_seg(int seg_reg, int selector) | ||
948 | 1033 | ||
949 | env->segs[seg_reg] = selector; | 1034 | env->segs[seg_reg] = selector; |
950 | sc = &env->seg_cache[seg_reg]; | 1035 | sc = &env->seg_cache[seg_reg]; |
951 | - if (env->vm86) { | 1036 | + if (env->eflags & VM_MASK) { |
952 | sc->base = (void *)(selector << 4); | 1037 | sc->base = (void *)(selector << 4); |
953 | sc->limit = 0xffff; | 1038 | sc->limit = 0xffff; |
954 | sc->seg_32bit = 0; | 1039 | sc->seg_32bit = 0; |
@@ -985,6 +1070,11 @@ void OPPROTO op_movl_T0_seg(void) | @@ -985,6 +1070,11 @@ void OPPROTO op_movl_T0_seg(void) | ||
985 | T0 = env->segs[PARAM1]; | 1070 | T0 = env->segs[PARAM1]; |
986 | } | 1071 | } |
987 | 1072 | ||
1073 | +void OPPROTO op_movl_A0_seg(void) | ||
1074 | +{ | ||
1075 | + A0 = *(unsigned long *)((char *)env + PARAM1); | ||
1076 | +} | ||
1077 | + | ||
988 | void OPPROTO op_addl_A0_seg(void) | 1078 | void OPPROTO op_addl_A0_seg(void) |
989 | { | 1079 | { |
990 | A0 += *(unsigned long *)((char *)env + PARAM1); | 1080 | A0 += *(unsigned long *)((char *)env + PARAM1); |
@@ -1144,10 +1234,16 @@ void OPPROTO op_set_cc_op(void) | @@ -1144,10 +1234,16 @@ void OPPROTO op_set_cc_op(void) | ||
1144 | CC_OP = PARAM1; | 1234 | CC_OP = PARAM1; |
1145 | } | 1235 | } |
1146 | 1236 | ||
1237 | +#define FL_UPDATE_MASK (TF_MASK | AC_MASK | ID_MASK) | ||
1238 | + | ||
1147 | void OPPROTO op_movl_eflags_T0(void) | 1239 | void OPPROTO op_movl_eflags_T0(void) |
1148 | { | 1240 | { |
1149 | - CC_SRC = T0; | ||
1150 | - DF = 1 - (2 * ((T0 >> 10) & 1)); | 1241 | + int eflags; |
1242 | + eflags = T0; | ||
1243 | + CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); | ||
1244 | + DF = 1 - (2 * ((eflags >> 10) & 1)); | ||
1245 | + /* we also update some system flags as in user mode */ | ||
1246 | + env->eflags = (env->eflags & ~FL_UPDATE_MASK) | (eflags & FL_UPDATE_MASK); | ||
1151 | } | 1247 | } |
1152 | 1248 | ||
1153 | /* XXX: compute only O flag */ | 1249 | /* XXX: compute only O flag */ |
@@ -1155,13 +1251,16 @@ void OPPROTO op_movb_eflags_T0(void) | @@ -1155,13 +1251,16 @@ void OPPROTO op_movb_eflags_T0(void) | ||
1155 | { | 1251 | { |
1156 | int of; | 1252 | int of; |
1157 | of = cc_table[CC_OP].compute_all() & CC_O; | 1253 | of = cc_table[CC_OP].compute_all() & CC_O; |
1158 | - CC_SRC = T0 | of; | 1254 | + CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of; |
1159 | } | 1255 | } |
1160 | 1256 | ||
1161 | void OPPROTO op_movl_T0_eflags(void) | 1257 | void OPPROTO op_movl_T0_eflags(void) |
1162 | { | 1258 | { |
1163 | - T0 = cc_table[CC_OP].compute_all(); | ||
1164 | - T0 |= (DF & DIRECTION_FLAG); | 1259 | + int eflags; |
1260 | + eflags = cc_table[CC_OP].compute_all(); | ||
1261 | + eflags |= (DF & DF_MASK); | ||
1262 | + eflags |= env->eflags & ~(VM_MASK | RF_MASK); | ||
1263 | + T0 = eflags; | ||
1165 | } | 1264 | } |
1166 | 1265 | ||
1167 | void OPPROTO op_cld(void) | 1266 | void OPPROTO op_cld(void) |