qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC PATCH 1/3] target-i386: Add 486sx, old486, and old486s


From: H. Peter Anvin
Subject: [Qemu-devel] [RFC PATCH 1/3] target-i386: Add 486sx, old486, and old486sx CPU models
Date: Wed, 27 Feb 2013 18:12:32 -0800

From: "H. Peter Anvin" <address@hidden>

Add models for 486SX, and pre-CPUID versions of the 486 (DX & SX).
Change the model number for the standard 486DX to a model which
actually had CPUID.

Note: these models are fairly vestigial, for example most of the FPU
operations still work; only F*ST[CS]W have been modified to appear as
through there is no FPU.

This also changes the classic 486 model number to 8 (DX4) which
matches the feature set presented.

Signed-off-by: H. Peter Anvin <address@hidden>
---
 target-i386/cpu.c         | 39 ++++++++++++++++++++++++++---
 target-i386/fpu_helper.c  | 12 +++++++--
 target-i386/misc_helper.c | 15 ++++++++----
 target-i386/translate.c   | 62 +++++++++++++++--------------------------------
 4 files changed, 75 insertions(+), 53 deletions(-)

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index aab35c7..a5aad19 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -365,8 +365,11 @@ typedef struct x86_def_t {
     uint32_t cpuid_7_0_ebx_features;
 } x86_def_t;
 
-#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
-#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
+#define OLD_I486SX_FEATURES 0
+#define OLD_I486_FEATURES CPUID_FP87
+#define I486SX_FEATURES CPUID_VME /* SX2+ */
+#define I486_FEATURES (CPUID_FP87 | CPUID_VME) /* DX4 and some DX2 */
+#define PENTIUM_FEATURES (I486_FEATURES | CPUID_PSE | CPUID_DE | CPUID_TSC | \
           CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
 #define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
           CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
@@ -535,16 +538,46 @@ static x86_def_t builtin_x86_defs[] = {
         .model_id = "Genuine Intel(R) CPU           T2600  @ 2.16GHz",
     },
     {
+        .name = "old486",
+        .level = 0,
+        .vendor = CPUID_VENDOR_INTEL,
+        .family = 4,
+        .model = 1,
+        .stepping = 0,
+        .features = OLD_I486_FEATURES,
+        .xlevel = 0,
+    },
+    {
+        .name = "old486sx",
+        .level = 0,
+        .vendor = CPUID_VENDOR_INTEL,
+        .family = 4,
+        .model = 2,
+        .stepping = 0,
+        .features = OLD_I486SX_FEATURES,
+        .xlevel = 0,
+    },
+    {
         .name = "486",
         .level = 1,
         .vendor = CPUID_VENDOR_INTEL,
         .family = 4,
-        .model = 0,
+        .model = 8,
         .stepping = 0,
         .features = I486_FEATURES,
         .xlevel = 0,
     },
     {
+        .name = "486sx",
+        .level = 1,
+        .vendor = CPUID_VENDOR_INTEL,
+        .family = 4,
+        .model = 5,
+        .stepping = 0,
+        .features = I486SX_FEATURES,
+        .xlevel = 0,
+    },
+    {
         .name = "pentium",
         .level = 1,
         .vendor = CPUID_VENDOR_INTEL,
diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c
index 44f3d27..c4c2724 100644
--- a/target-i386/fpu_helper.c
+++ b/target-i386/fpu_helper.c
@@ -530,12 +530,20 @@ void helper_fldz_FT0(CPUX86State *env)
 
 uint32_t helper_fnstsw(CPUX86State *env)
 {
-    return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
+    if (!(env->cpuid_features & CPUID_FP87)) {
+        return 0xffff;
+    } else {
+        return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
+    }
 }
 
 uint32_t helper_fnstcw(CPUX86State *env)
 {
-    return env->fpuc;
+    if (!(env->cpuid_features & CPUID_FP87)) {
+        return 0xffff;
+    } else {
+        return env->fpuc;
+    }
 }
 
 static void update_fp_status(CPUX86State *env)
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index b6d5740..1ff25d1 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -122,11 +122,16 @@ void helper_cpuid(CPUX86State *env)
 
     cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0);
 
-    cpu_x86_cpuid(env, (uint32_t)EAX, (uint32_t)ECX, &eax, &ebx, &ecx, &edx);
-    EAX = eax;
-    EBX = ebx;
-    ECX = ecx;
-    EDX = edx;
+    if (!env->cpuid_level) {
+        raise_exception_err(env, EXCP06_ILLOP, 0);
+    } else {
+        cpu_x86_cpuid(env, (uint32_t)EAX, (uint32_t)ECX,
+                      &eax, &ebx, &ecx, &edx);
+        EAX = eax;
+        EBX = ebx;
+        ECX = ecx;
+        EDX = edx;
+    }
 }
 
 #if defined(CONFIG_USER_ONLY)
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 112c310..6d8abff 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -103,6 +103,8 @@ typedef struct DisasContext {
     struct TranslationBlock *tb;
     int popl_esp_hack; /* for correct popl with esp base handling */
     int rip_offset; /* only used in x86_64, but left for simplicity */
+    int cpuid_family;
+    int cpuid_level;
     int cpuid_features;
     int cpuid_ext_features;
     int cpuid_ext2_features;
@@ -6513,52 +6515,24 @@ static target_ulong disas_insn(CPUX86State *env, 
DisasContext *s,
         if (s->vm86 && s->iopl != 3) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
         } else {
+            uint32_t mask;
             gen_pop_T0(s);
+            mask = TF_MASK | NT_MASK | IF_MASK;
+            if (s->cpuid_family >= 4) {
+                mask |= AC_MASK;
+            }
+            if (s->cpuid_level) {
+                mask |= ID_MASK;
+            }
             if (s->cpl == 0) {
-                if (s->dflag) {
-                    gen_helper_write_eflags(cpu_env, cpu_T[0],
-                                            tcg_const_i32((TF_MASK | AC_MASK |
-                                                           ID_MASK | NT_MASK |
-                                                           IF_MASK |
-                                                           IOPL_MASK)));
-                } else {
-                    gen_helper_write_eflags(cpu_env, cpu_T[0],
-                                            tcg_const_i32((TF_MASK | AC_MASK |
-                                                           ID_MASK | NT_MASK |
-                                                           IF_MASK | IOPL_MASK)
-                                                          & 0xffff));
-                }
-            } else {
-                if (s->cpl <= s->iopl) {
-                    if (s->dflag) {
-                        gen_helper_write_eflags(cpu_env, cpu_T[0],
-                                                tcg_const_i32((TF_MASK |
-                                                               AC_MASK |
-                                                               ID_MASK |
-                                                               NT_MASK |
-                                                               IF_MASK)));
-                    } else {
-                        gen_helper_write_eflags(cpu_env, cpu_T[0],
-                                                tcg_const_i32((TF_MASK |
-                                                               AC_MASK |
-                                                               ID_MASK |
-                                                               NT_MASK |
-                                                               IF_MASK)
-                                                              & 0xffff));
-                    }
-                } else {
-                    if (s->dflag) {
-                        gen_helper_write_eflags(cpu_env, cpu_T[0],
-                                           tcg_const_i32((TF_MASK | AC_MASK |
-                                                          ID_MASK | NT_MASK)));
-                    } else {
-                        gen_helper_write_eflags(cpu_env, cpu_T[0],
-                                           tcg_const_i32((TF_MASK | AC_MASK |
-                                                          ID_MASK | NT_MASK)
-                                                         & 0xffff));
-                    }
-                }
+                mask |= IF_MASK | IOPL_MASK;
+            } else if (s->cpl <= s->iopl) {
+                mask |= IF_MASK;
+            }
+            if (!s->dflag) {
+                mask &= 0xffff;
             }
+            gen_helper_write_eflags(cpu_env, cpu_T[0], tcg_const_i32(mask));
             gen_pop_update(s);
             s->cc_op = CC_OP_EFLAGS;
             /* abort translation because TF/AC flag may change */
@@ -7926,6 +7900,8 @@ static inline void 
gen_intermediate_code_internal(CPUX86State *env,
     if (flags & HF_SOFTMMU_MASK) {
         dc->mem_index = (cpu_mmu_index(env) + 1) << 2;
     }
+    dc->cpuid_family = (env->cpuid_version >> 8) & 0x0f;
+    dc->cpuid_level = env->cpuid_level;
     dc->cpuid_features = env->cpuid_features;
     dc->cpuid_ext_features = env->cpuid_ext_features;
     dc->cpuid_ext2_features = env->cpuid_ext2_features;
-- 
1.7.11.7




reply via email to

[Prev in Thread] Current Thread [Next in Thread]