diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 88e5eace003..df83094750e 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -2814,9 +2814,12 @@ void *signal_init_syscalls(void) void *ptr, *syscall_dispatcher; extern void __wine_syscall_dispatcher_xsave(void) DECLSPEC_HIDDEN; + extern void __wine_syscall_dispatcher_xsavec(void) DECLSPEC_HIDDEN; NtQuerySystemInformation( SystemCpuInformation, &cpu_info, sizeof(cpu_info), NULL ); - if (cpu_info.FeatureSet & CPU_FEATURE_XSAVE) + if (cpu_info.FeatureSet & CPU_FEATURE_XSAVEC) + syscall_dispatcher = __wine_syscall_dispatcher_xsavec; + else if (cpu_info.FeatureSet & CPU_FEATURE_XSAVE) syscall_dispatcher = __wine_syscall_dispatcher_xsave; else syscall_dispatcher = __wine_syscall_dispatcher; diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index 6cf044d496f..27ecfae365f 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -305,6 +305,12 @@ static void get_cpuinfo( SYSTEM_CPU_INFORMATION *info ) if (regs3[1] & (1 << 5)) info->FeatureSet |= CPU_FEATURE_AVX2; } + if (info->FeatureSet & CPU_FEATURE_XSAVE) + { + do_cpuid( 0x0000000d, regs3 ); /* get XSAVE details */ + if (regs3[0] & 2) info->FeatureSet |= CPU_FEATURE_XSAVEC; + } + if (regs[1] == AUTH && regs[3] == ENTI && regs[2] == CAMD) { info->Level = (regs2[0] >> 8) & 0xf; /* family */ diff --git a/include/winternl.h b/include/winternl.h index 76feca83596..3beecf10ff6 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1754,6 +1754,7 @@ typedef struct _SYSTEM_CPU_INFORMATION { /* FIXME: following values are made up, actual flags are unknown */ #define CPU_FEATURE_SSSE3 0x00008000 /* SSSE3 instructions */ +#define CPU_FEATURE_XSAVEC 0x00400000 /* XSAVEC instructions */ #define CPU_FEATURE_SSE41 0x01000000 /* SSE41 instructions */ #define CPU_FEATURE_SSE42 0x02000000 /* SSE42 instructions */ #define CPU_FEATURE_AVX 0x40000000 /* AVX instructions */ diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index a01694ffb9c..2fa9d3d430b 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1534,7 +1534,17 @@ static void output_syscall_dispatcher( int count, const char *variant ) output( "\tmovq %%rdx,0x200(%%r12)\n" ); output( "\tmovq %%rdx,0x208(%%r12)\n" ); output( "\tmovq %%rdx,0x210(%%r12)\n" ); - output( "\txsave64 (%%r12)\n" ); + if (!strcmp( variant, "_xsavec" )) + { + output( "\tmovq %%rdx,0x218(%%r12)\n" ); + output( "\tmovq %%rdx,0x220(%%r12)\n" ); + output( "\tmovq %%rdx,0x228(%%r12)\n" ); + output( "\tmovq %%rdx,0x230(%%r12)\n" ); + output( "\tmovq %%rdx,0x238(%%r12)\n" ); + output( "\txsavec64 (%%r12)\n" ); + } + else + output( "\txsave64 (%%r12)\n" ); output( "\tmovq %%rsi,%%rdx\n" ); } output( "\tmovq %%gs:0x30,%%rcx\n" ); @@ -1740,6 +1750,7 @@ void output_syscalls( DLLSPEC *spec ) { case CPU_x86_64: output_syscall_dispatcher( count, "_xsave" ); + output_syscall_dispatcher( count, "_xsavec" ); break; default: break;