Brendan Shanks : wow64: Copy floating point and extended registers in copy_context_64to32.

Alexandre Julliard julliard at winehq.org
Wed Aug 3 15:31:40 CDT 2022


Module: wine
Branch: master
Commit: 2599042221d7bcbafd2646178b47801fb080c1ae
URL:    https://gitlab.winehq.org/wine/wine/-/commit/2599042221d7bcbafd2646178b47801fb080c1ae

Author: Brendan Shanks <bshanks at codeweavers.com>
Date:   Tue Aug  2 10:40:09 2022 -0700

wow64: Copy floating point and extended registers in copy_context_64to32.

---

 dlls/wow64cpu/cpu.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/dlls/wow64cpu/cpu.c b/dlls/wow64cpu/cpu.c
index 34c3f3ad493..fa1c22aafc6 100644
--- a/dlls/wow64cpu/cpu.c
+++ b/dlls/wow64cpu/cpu.c
@@ -53,6 +53,51 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, void *reserved )
     return TRUE;
 }
 
+/***********************************************************************
+ *           fpux_to_fpu
+ *
+ * Build a standard i386 FPU context from an extended one.
+ */
+static void fpux_to_fpu( I386_FLOATING_SAVE_AREA *fpu, const XMM_SAVE_AREA32 *fpux )
+{
+    unsigned int i, tag, stack_top;
+
+    fpu->ControlWord   = fpux->ControlWord;
+    fpu->StatusWord    = fpux->StatusWord;
+    fpu->ErrorOffset   = fpux->ErrorOffset;
+    fpu->ErrorSelector = fpux->ErrorSelector | (fpux->ErrorOpcode << 16);
+    fpu->DataOffset    = fpux->DataOffset;
+    fpu->DataSelector  = fpux->DataSelector;
+    fpu->Cr0NpxState   = fpux->StatusWord | 0xffff0000;
+
+    stack_top = (fpux->StatusWord >> 11) & 7;
+    fpu->TagWord = 0xffff0000;
+    for (i = 0; i < 8; i++)
+    {
+        memcpy( &fpu->RegisterArea[10 * i], &fpux->FloatRegisters[i], 10 );
+        if (!(fpux->TagWord & (1 << i))) tag = 3;  /* empty */
+        else
+        {
+            const M128A *reg = &fpux->FloatRegisters[(i - stack_top) & 7];
+            if ((reg->High & 0x7fff) == 0x7fff)  /* exponent all ones */
+            {
+                tag = 2;  /* special */
+            }
+            else if (!(reg->High & 0x7fff))  /* exponent all zeroes */
+            {
+                if (reg->Low) tag = 2;  /* special */
+                else tag = 1;  /* zero */
+            }
+            else
+            {
+                if (reg->Low >> 63) tag = 0;  /* valid */
+                else tag = 2;  /* special */
+            }
+        }
+        fpu->TagWord |= tag << (2 * i);
+    }
+}
+
 /**********************************************************************
  *           copy_context_64to32
  *
@@ -97,7 +142,15 @@ static void copy_context_64to32( I386_CONTEXT *ctx32, DWORD flags, AMD64_CONTEXT
         ctx32->Dr6 = ctx64->Dr6;
         ctx32->Dr7 = ctx64->Dr7;
     }
-    /* FIXME: floating point + xstate */
+    if (flags & CONTEXT_I386_FLOATING_POINT)
+    {
+        fpux_to_fpu( &ctx32->FloatSave, &ctx64->FltSave );
+    }
+    if (flags & CONTEXT_I386_EXTENDED_REGISTERS)
+    {
+        *(XSAVE_FORMAT *)ctx32->ExtendedRegisters = ctx64->FltSave;
+    }
+    /* FIXME: xstate */
 }
 
 




More information about the wine-cvs mailing list