Patchwork [47/49] x86: factor out cpu_get/put_fpreg()

login
register
mail settings
Submitter Juan Quintela
Date Sept. 29, 2009, 8:49 p.m.
Message ID <9abd7eeda46d67842bb0505ce3571fa5019402be.1254255997.git.quintela@redhat.com>
Download mbox | patch
Permalink /patch/34500/
State Superseded
Headers show

Comments

Juan Quintela - Sept. 29, 2009, 8:49 p.m.
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 target-i386/machine.c |  209 ++++++++++++++++++++++++++++++++-----------------
 1 files changed, 137 insertions(+), 72 deletions(-)

Patch

diff --git a/target-i386/machine.c b/target-i386/machine.c
index 18f8845..5a530b5 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -75,6 +75,120 @@  static void cpu_get_mtrr_var(QEMUFile *f, MTRRVar *mtrr_var)
     vmstate_load_state(f, &vmstate_mtrr_var, mtrr_var, vmstate_mtrr_var.version_id);
 }

+#ifdef USE_X86LDOUBLE
+/* XXX: add that in a FPU generic layer */
+union x86_longdouble {
+    uint64_t mant;
+    uint16_t exp;
+};
+
+#define MANTD1(fp)	(fp & ((1LL << 52) - 1))
+#define EXPBIAS1 1023
+#define EXPD1(fp)	((fp >> 52) & 0x7FF)
+#define SIGND1(fp)	((fp >> 32) & 0x80000000)
+
+static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
+{
+    int e;
+    /* mantissa */
+    p->mant = (MANTD1(temp) << 11) | (1LL << 63);
+    /* exponent + sign */
+    e = EXPD1(temp) - EXPBIAS1 + 16383;
+    e |= SIGND1(temp) >> 16;
+    p->exp = e;
+}
+
+static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
+{
+    FPReg *fp_reg = opaque;
+    uint64_t mant;
+    uint16_t exp;
+
+    qemu_get_be64s(f, &mant);
+    qemu_get_be16s(f, &exp);
+    fp_reg->d = cpu_set_fp80(mant, exp);
+    return 0;
+}
+
+static void put_fpreg(QEMUFile *f, void *opaque, size_t size)
+{
+    FPReg *fp_reg = opaque;
+    uint64_t mant;
+    uint16_t exp;
+    /* we save the real CPU data (in case of MMX usage only 'mant'
+       contains the MMX register */
+    cpu_get_fp80(&mant, &exp, fp_reg->d);
+    qemu_put_be64s(f, &mant);
+    qemu_put_be16s(f, &exp);
+}
+
+static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size)
+{
+    union x86_longdouble *p = opaque;
+    uint64_t mant;
+
+    qemu_get_be64s(f, &mant);
+    p->mant = mant;
+    p->exp = 0xffff;
+    return 0;
+}
+
+static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size)
+{
+    union x86_longdouble *p = opaque;
+    uint64_t mant;
+
+    qemu_get_be64s(f, &mant);
+    fp64_to_fp80(p, mant);
+    return 0;
+}
+
+#else
+static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
+{
+    FPReg *fp_reg = opaque;
+
+    qemu_get_be64s(f, &fp_reg->mmx.MMX_Q(0));
+    return 0;
+}
+
+static void put_fpreg(QEMUFile *f, void *opaque, size_t size)
+{
+    FPReg *fp_reg = opaque;
+    /* if we use doubles for float emulation, we save the doubles to
+       avoid losing information in case of MMX usage. It can give
+       problems if the image is restored on a CPU where long
+       doubles are used instead. */
+    qemu_put_be64s(f, &fp_reg->mmx.MMX_Q(0));
+}
+
+static int get_fpreg_0_mmx(QEMUFile *f, void *opaque, size_t size)
+{
+    FPReg *fp_reg = opaque;
+    uint64_t mant;
+    uint16_t exp;
+
+    qemu_get_be64s(f, &mant);
+    qemu_get_be16s(f, &exp);
+    fp_reg->mmx.MMX_Q(0) = mant;
+    return 0;
+}
+
+static int get_fpreg_0_no_mmx(QEMUFile *f, void *opaque, size_t size)
+{
+    FPReg *fp_reg = opaque;
+    uint64_t mant;
+    uint16_t exp;
+
+    qemu_get_be64s(f, &mant);
+    qemu_get_be16s(f, &exp);
+
+    fp_reg->d = cpu_set_fp80(mant, exp);
+    return 0;
+}
+
+#endif /* USE_X86LDOUBLE */
+
 static void cpu_pre_save(void *opaque)
 {
     CPUState *env = opaque;
@@ -128,23 +242,7 @@  void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be16s(f, &env->fpregs_format_vmstate);

     for(i = 0; i < 8; i++) {
-#ifdef USE_X86LDOUBLE
-        {
-            uint64_t mant;
-            uint16_t exp;
-            /* we save the real CPU data (in case of MMX usage only 'mant'
-               contains the MMX register */
-            cpu_get_fp80(&mant, &exp, env->fpregs[i].d);
-            qemu_put_be64(f, mant);
-            qemu_put_be16(f, exp);
-        }
-#else
-        /* if we use doubles for float emulation, we save the doubles to
-           avoid losing information in case of MMX usage. It can give
-           problems if the image is restored on a CPU where long
-           doubles are used instead. */
-        qemu_put_be64(f, env->fpregs[i].mmx.MMX_Q(0));
-#endif
+        put_fpreg(f, &env->fpregs[i], 0);
     }

     for(i = 0; i < 6; i++)
@@ -222,30 +320,6 @@  void cpu_save(QEMUFile *f, void *opaque)
     }
  }

-#ifdef USE_X86LDOUBLE
-/* XXX: add that in a FPU generic layer */
-union x86_longdouble {
-    uint64_t mant;
-    uint16_t exp;
-};
-
-#define MANTD1(fp)	(fp & ((1LL << 52) - 1))
-#define EXPBIAS1 1023
-#define EXPD1(fp)	((fp >> 52) & 0x7FF)
-#define SIGND1(fp)	((fp >> 32) & 0x80000000)
-
-static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
-{
-    int e;
-    /* mantissa */
-    p->mant = (MANTD1(temp) << 11) | (1LL << 63);
-    /* exponent + sign */
-    e = EXPD1(temp) - EXPBIAS1 + 16383;
-    e |= SIGND1(temp) >> 16;
-    p->exp = e;
-}
-#endif
-
 static int cpu_pre_load(void *opaque)
 {
     CPUState *env = opaque;
@@ -304,49 +378,40 @@  int cpu_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_be16s(f, &env->fptag_vmstate);
     qemu_get_be16s(f, &env->fpregs_format_vmstate);

-    /* NOTE: we cannot always restore the FPU state if the image come
-       from a host with a different 'USE_X86LDOUBLE' define. We guess
-       if we are in an MMX state to restore correctly in that case. */
     guess_mmx = ((env->fptag_vmstate == 0xff) && (env->fpus_vmstate & 0x3800) == 0);
-    for(i = 0; i < 8; i++) {
-        uint64_t mant;
-        uint16_t exp;

+    for(i = 0; i < 8; i++) {
+#ifdef USE_X86LDOUBLE
         switch(env->fpregs_format_vmstate) {
         case 0:
-            mant = qemu_get_be64(f);
-            exp = qemu_get_be16(f);
-#ifdef USE_X86LDOUBLE
-            env->fpregs[i].d = cpu_set_fp80(mant, exp);
-#else
-            /* difficult case */
-            if (guess_mmx)
-                env->fpregs[i].mmx.MMX_Q(0) = mant;
-            else
-                env->fpregs[i].d = cpu_set_fp80(mant, exp);
-#endif
+            get_fpreg(f, &env->fpregs[i], 0);
             break;
         case 1:
-            mant = qemu_get_be64(f);
-#ifdef USE_X86LDOUBLE
-            {
-                union x86_longdouble *p;
-                /* difficult case */
-                p = (void *)&env->fpregs[i];
-                if (guess_mmx) {
-                    p->mant = mant;
-                    p->exp = 0xffff;
-                } else {
-                    fp64_to_fp80(p, mant);
-                }
+            if (guess_mmx) {
+                get_fpreg_1_mmx(f, &env->fpregs[i], 0);
+            } else {
+                get_fpreg_1_no_mmx(f, &env->fpregs[i], 0);
             }
+            break;
+        default:
+            return -EINVAL;
+        }
 #else
-            env->fpregs[i].mmx.MMX_Q(0) = mant;
-#endif
+        switch(env->fpregs_format_vmstate) {
+        case 0:
+            if (guess_mmx) {
+                get_fpreg_0_mmx(f, &env->fpregs[i], 0);
+            } else {
+                get_fpreg_0_no_mmx(f, &env->fpregs[i], 0);
+            }
+            break;
+        case 1:
+            get_fpreg(f, &env->fpregs[i], 0);
             break;
         default:
             return -EINVAL;
         }
+#endif
     }

     for(i = 0; i < 6; i++)