Jacek Caban : ntdll: Use xsave compaction in syscall dispatcher.

Alexandre Julliard julliard at winehq.org
Wed Mar 3 15:47:30 CST 2021


Module: wine
Branch: master
Commit: e979ee96b6c4d4bba9e9572603599867fdb321ca
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e979ee96b6c4d4bba9e9572603599867fdb321ca

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Mar  3 15:54:11 2021 +0100

ntdll: Use xsave compaction in syscall dispatcher.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/unix/signal_i386.c | 56 ++++++++++++++++++++++++++++++++++++++-----
 tools/winebuild/import.c      | 13 +++++++++-
 2 files changed, 62 insertions(+), 7 deletions(-)

diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c
index d9d7e66ca32..655fd69ee73 100644
--- a/dlls/ntdll/unix/signal_i386.c
+++ b/dlls/ntdll/unix/signal_i386.c
@@ -1225,17 +1225,20 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
         memcpy( &xsave->u.xsave, context->ExtendedRegisters, sizeof(xsave->u.xsave) );
         /* reset the current interrupt status */
         xsave->u.xsave.StatusWord &= xsave->u.xsave.ControlWord | 0xff80;
+        xsave->xstate.mask |= XSTATE_MASK_LEGACY;
     }
     else if (flags & CONTEXT_FLOATING_POINT)
     {
+        struct syscall_xsave *xsave = get_syscall_xsave( frame );
         if (cpu_info.FeatureSet & CPU_FEATURE_FXSR)
         {
-            fpu_to_fpux( &get_syscall_xsave( frame )->u.xsave, &context->FloatSave );
+            fpu_to_fpux( &xsave->u.xsave, &context->FloatSave );
         }
         else
         {
-            get_syscall_xsave( frame )->u.fsave = context->FloatSave;
+            xsave->u.fsave = context->FloatSave;
         }
+        xsave->xstate.mask |= XSTATE_MASK_LEGACY_FLOATING_POINT;
     }
     if ((cpu_info.FeatureSet & CPU_FEATURE_AVX) && (xs = xstate_from_context( context )))
     {
@@ -1323,15 +1326,53 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
         }
         if (needed_flags & CONTEXT_FLOATING_POINT)
         {
-            if (cpu_info.FeatureSet & CPU_FEATURE_FXSR)
+            if (!(cpu_info.FeatureSet & CPU_FEATURE_FXSR))
+            {
+                context->FloatSave = xsave->u.fsave;
+            }
+            else if (!xstate_compaction_enabled ||
+                     (xsave->xstate.mask & XSTATE_MASK_LEGACY_FLOATING_POINT))
+            {
                 fpux_to_fpu( &context->FloatSave, &xsave->u.xsave );
+            }
             else
-                context->FloatSave = xsave->u.fsave;
+            {
+                memset( &context->FloatSave, 0, sizeof(context->FloatSave) );
+                context->FloatSave.ControlWord = 0x37f;
+            }
             context->ContextFlags |= CONTEXT_FLOATING_POINT;
         }
         if (needed_flags & CONTEXT_EXTENDED_REGISTERS)
         {
-            memcpy( context->ExtendedRegisters, &xsave->u.xsave, sizeof(xsave->u.xsave) );
+            XSAVE_FORMAT *xs = (XSAVE_FORMAT *)context->ExtendedRegisters;
+
+            if (!xstate_compaction_enabled ||
+                (xsave->xstate.mask & XSTATE_MASK_LEGACY_FLOATING_POINT))
+            {
+                memcpy( xs, &xsave->u.xsave, FIELD_OFFSET( XSAVE_FORMAT, MxCsr ));
+                memcpy( xs->FloatRegisters, xsave->u.xsave.FloatRegisters,
+                        sizeof( xs->FloatRegisters ));
+            }
+            else
+            {
+                memset( xs, 0, FIELD_OFFSET( XSAVE_FORMAT, MxCsr ));
+                memset( xs->FloatRegisters, 0, sizeof( xs->FloatRegisters ));
+                xs->ControlWord = 0x37f;
+            }
+
+            if (!xstate_compaction_enabled || (xsave->xstate.mask & XSTATE_MASK_LEGACY_SSE))
+            {
+                memcpy( xs->XmmRegisters, xsave->u.xsave.XmmRegisters, sizeof( xs->XmmRegisters ));
+                xs->MxCsr      = xsave->u.xsave.MxCsr;
+                xs->MxCsr_Mask = xsave->u.xsave.MxCsr_Mask;
+            }
+            else
+            {
+                memset( xs->XmmRegisters, 0, sizeof( xs->XmmRegisters ));
+                xs->MxCsr      = 0x1f80;
+                xs->MxCsr_Mask = 0x2ffff;
+            }
+
             context->ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
         }
         /* update the cached version of the debug registers */
@@ -2528,8 +2569,11 @@ void *signal_init_syscalls(void)
 {
     extern void __wine_syscall_dispatcher_fxsave(void) DECLSPEC_HIDDEN;
     extern void __wine_syscall_dispatcher_xsave(void) DECLSPEC_HIDDEN;
+    extern void __wine_syscall_dispatcher_xsavec(void) DECLSPEC_HIDDEN;
 
-    if (cpu_info.FeatureSet & CPU_FEATURE_XSAVE)
+    if (xstate_compaction_enabled)
+        syscall_dispatcher = __wine_syscall_dispatcher_xsavec;
+    else if (cpu_info.FeatureSet & CPU_FEATURE_XSAVE)
         syscall_dispatcher = __wine_syscall_dispatcher_xsave;
     else if (cpu_info.FeatureSet & CPU_FEATURE_FXSR)
         syscall_dispatcher = __wine_syscall_dispatcher_fxsave;
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index 073ad9b10cf..b745f16db42 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -1468,7 +1468,7 @@ static void output_syscall_dispatcher( int count, const char *variant )
         {
             output( "\tfxsave (%%esp)\n" );
         }
-        else
+        else if(!strcmp( variant, "_xsave" ))
         {
             output( "\tmovl %%eax,%%ecx\n ");
             output( "\tmovl $7,%%eax\n" );
@@ -1478,6 +1478,16 @@ static void output_syscall_dispatcher( int count, const char *variant )
             output( "\txsave (%%esp)\n" );
             output( "\tmovl %%ecx,%%eax\n ");
         }
+        else /* _xsavec */
+        {
+            output( "\tmovl %%eax,%%ecx\n ");
+            output( "\tmovl $7,%%eax\n" );
+            output( "\txorl %%edx,%%edx\n" );
+            for (i = 0; i < 16; i++)
+                output( "\tmovl %%edx,0x%x(%%esp)\n", 0x200 + i * 4 );
+            output( "\txsavec (%%esp)\n" );
+            output( "\tmovl %%ecx,%%eax\n ");
+        }
         output( "\tleal -0x30(%%ebp),%%ecx\n" );
         output( "\tmovl %%ecx,%%fs:0x1f8\n" );  /* x86_thread_data()->syscall_frame */
         output( "\tcmpl $%u,%%eax\n", count );
@@ -1837,6 +1847,7 @@ void output_syscalls( DLLSPEC *spec )
         case CPU_x86:
             output_syscall_dispatcher( count, "_fxsave" );
             output_syscall_dispatcher( count, "_xsave" );
+            output_syscall_dispatcher( count, "_xsavec" );
             break;
         case CPU_x86_64:
             output_syscall_dispatcher( count, "_xsave" );




More information about the wine-cvs mailing list