Commit a4a0ffdb2be25b381df38758b1b0a32ae04491d0

Authored by bellard
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)
... ...