The GDB stub was returning a hardcoded 0 for the x87 FPU tag word
register (ftag). Factor out cpu_compute_fptag() helper. Simplify a
little bit the code by dropping unnecessary CPU_LDoubleU
reinterpretation, building the value 0..7, avoiding signed-shifting.

Signed-off-by: Marc-André Lureau <[email protected]>
---
 target/i386/cpu.c            | 28 ++++++++++++++++++++++++++++
 target/i386/cpu.h            |  9 +++++++++
 target/i386/gdbstub.c        |  2 +-
 target/i386/tcg/fpu_helper.c | 24 ++----------------------
 4 files changed, 40 insertions(+), 23 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 37732b65e408..2f5ea4e51715 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -9372,6 +9372,34 @@ static bool cpuid_has_xsave_feature(CPUX86State *env, 
const ExtSaveArea *esa)
     return false;
 }
 
+uint16_t cpu_compute_fptag(CPUX86State *env)
+{
+    uint16_t fptag = 0;
+
+    for (int i = 0; i < 8; i++) {
+        unsigned tag;
+
+        if (env->fptags[i]) {
+            tag = 3; /* empty */
+        } else {
+            floatx80 f = env->fpregs[i].d;
+            uint16_t exponent = f.high & 0x7fff;
+            uint64_t mantissa = f.low;
+
+            if (exponent == 0 && mantissa == 0) {
+                tag = 1; /* zero */
+            } else if (exponent == 0 || exponent == 0x7fff ||
+                       !(mantissa & (1ULL << 63))) {
+                tag = 2; /* NaNs, infinity, denormal */
+            } else {
+                tag = 0; /* valid */
+            }
+        }
+        fptag |= tag << (2 * i);
+    }
+    return fptag;
+}
+
 static void x86_cpu_reset_hold(Object *obj, ResetType type)
 {
     CPUState *cs = CPU(obj);
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index e7a88074c071..116e28a59701 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -2989,6 +2989,15 @@ static inline void cpu_set_mxcsr(CPUX86State *env, 
uint32_t mxcsr)
     }
 }
 
+/**
+ * cpu_compute_fptag - Compute the full 16-bit x87 FPU tag word.
+ *
+ * Reconstructs the 16-bit tag word from the fpregs and fptags arrays.
+ * Each of the 8 physical registers gets a 2-bit tag in bits [2*i+1 : 2*i]:
+ *   0 = valid, 1 = zero, 2 = special (NaN/Inf/denormal), 3 = empty.
+ */
+uint16_t cpu_compute_fptag(CPUX86State *env);
+
 static inline void cpu_set_fpuc(CPUX86State *env, uint16_t fpuc)
 {
      env->fpuc = fpuc;
diff --git a/target/i386/gdbstub.c b/target/i386/gdbstub.c
index c0cde26d978c..420ce845eeae 100644
--- a/target/i386/gdbstub.c
+++ b/target/i386/gdbstub.c
@@ -186,7 +186,7 @@ int x86_cpu_gdb_read_register(CPUState *cs, GByteArray 
*mem_buf, int n)
             return gdb_get_reg32(mem_buf, (env->fpus & ~0x3800) |
                                           (env->fpstt & 0x7) << 11);
         case IDX_FP_REGS + 10:
-            return gdb_get_reg32(mem_buf, 0); /* ftag */
+            return gdb_get_reg32(mem_buf, cpu_compute_fptag(env));
         case IDX_FP_REGS + 11:
             return gdb_get_reg32(mem_buf, 0); /* fiseg */
         case IDX_FP_REGS + 12:
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
index 4bbac996326e..81ae3d8f3d0f 100644
--- a/target/i386/tcg/fpu_helper.c
+++ b/target/i386/tcg/fpu_helper.c
@@ -2459,30 +2459,10 @@ void helper_fxam_ST0(CPUX86State *env)
 static void do_fstenv(X86Access *ac, target_ulong ptr, int data32)
 {
     CPUX86State *env = ac->env;
-    int fpus, fptag, exp, i;
-    uint64_t mant;
-    CPU_LDoubleU tmp;
+    int fpus, fptag;
 
     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
-    fptag = 0;
-    for (i = 7; i >= 0; i--) {
-        fptag <<= 2;
-        if (env->fptags[i]) {
-            fptag |= 3;
-        } else {
-            tmp.d = env->fpregs[i].d;
-            exp = EXPD(tmp);
-            mant = MANTD(tmp);
-            if (exp == 0 && mant == 0) {
-                /* zero */
-                fptag |= 1;
-            } else if (exp == 0 || exp == MAXEXPD
-                       || (mant & (1LL << 63)) == 0) {
-                /* NaNs, infinity, denormal */
-                fptag |= 2;
-            }
-        }
-    }
+    fptag = cpu_compute_fptag(env);
     if (data32) {
         /* 32 bit */
         access_stl(ac, ptr, env->fpuc);

-- 
2.56.0.116.g6de20f6092dc


Reply via email to