ntdll: Use xsave compaction in syscall dispatcher.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2021-03-03 15:54:11 +01:00 committed by Alexandre Julliard
parent c715243122
commit e979ee96b6
2 changed files with 63 additions and 8 deletions

View File

@ -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)
fpux_to_fpu( &context->FloatSave, &xsave->u.xsave );
else
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
{
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;

View File

@ -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" );