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 | 607 | int eflags; |
608 | 608 | eflags = cc_table[CC_OP].compute_all(); |
609 | 609 | if (eflags & CC_O) { |
610 | - EIP = PARAM1; | |
611 | 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 | 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 | 655 | /* string ops */ |
... | ... | @@ -793,7 +831,8 @@ void op_addw_ESP_im(void) |
793 | 831 | #ifndef __i386__ |
794 | 832 | uint64_t emu_time; |
795 | 833 | #endif |
796 | -void op_rdtsc(void) | |
834 | + | |
835 | +void OPPROTO op_rdtsc(void) | |
797 | 836 | { |
798 | 837 | uint64_t val; |
799 | 838 | #ifdef __i386__ |
... | ... | @@ -806,6 +845,51 @@ void op_rdtsc(void) |
806 | 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 | 893 | /* bcd */ |
810 | 894 | |
811 | 895 | /* XXX: exception */ |
... | ... | @@ -938,6 +1022,7 @@ void OPPROTO op_das(void) |
938 | 1022 | |
939 | 1023 | /* segment handling */ |
940 | 1024 | |
1025 | +/* XXX: use static VM86 information */ | |
941 | 1026 | void load_seg(int seg_reg, int selector) |
942 | 1027 | { |
943 | 1028 | SegmentCache *sc; |
... | ... | @@ -948,7 +1033,7 @@ void load_seg(int seg_reg, int selector) |
948 | 1033 | |
949 | 1034 | env->segs[seg_reg] = selector; |
950 | 1035 | sc = &env->seg_cache[seg_reg]; |
951 | - if (env->vm86) { | |
1036 | + if (env->eflags & VM_MASK) { | |
952 | 1037 | sc->base = (void *)(selector << 4); |
953 | 1038 | sc->limit = 0xffff; |
954 | 1039 | sc->seg_32bit = 0; |
... | ... | @@ -985,6 +1070,11 @@ void OPPROTO op_movl_T0_seg(void) |
985 | 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 | 1078 | void OPPROTO op_addl_A0_seg(void) |
989 | 1079 | { |
990 | 1080 | A0 += *(unsigned long *)((char *)env + PARAM1); |
... | ... | @@ -1144,10 +1234,16 @@ void OPPROTO op_set_cc_op(void) |
1144 | 1234 | CC_OP = PARAM1; |
1145 | 1235 | } |
1146 | 1236 | |
1237 | +#define FL_UPDATE_MASK (TF_MASK | AC_MASK | ID_MASK) | |
1238 | + | |
1147 | 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 | 1249 | /* XXX: compute only O flag */ |
... | ... | @@ -1155,13 +1251,16 @@ void OPPROTO op_movb_eflags_T0(void) |
1155 | 1251 | { |
1156 | 1252 | int of; |
1157 | 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 | 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 | 1266 | void OPPROTO op_cld(void) | ... | ... |