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) | ... | ... |