From edbdec441b80dbc06f3878b7e4d823735f2888ec Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 14 Feb 2019 19:46:16 +0100 Subject: [PATCH] ntdll: Store extended FPU context in NtGetContextThread(). Signed-off-by: Alexandre Julliard --- dlls/ntdll/signal_i386.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 1b3b10fd6ad..3ce10d30251 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -427,8 +427,6 @@ static size_t signal_stack_size; static wine_signal_handler handlers[256]; -static BOOL fpux_support; /* whether the CPU supports extended fpu context */ - enum i386_trap_code { TRAP_x86_UNKNOWN = -1, /* Unknown fault (TRAP_sig not defined) */ @@ -558,6 +556,15 @@ static inline void *get_signal_stack(void) } +/*********************************************************************** + * has_fpux + */ +static inline int has_fpux(void) +{ + return (cpu_info.FeatureSet & CPU_FEATURE_FXSR); +} + + /*********************************************************************** * get_current_teb * @@ -859,6 +866,26 @@ static inline void save_fpu( CONTEXT *context ) } +/*********************************************************************** + * save_fpux + * + * Save the thread FPU extended context. + */ +static inline void save_fpux( CONTEXT *context ) +{ +#ifdef __GNUC__ + /* we have to enforce alignment by hand */ + char buffer[sizeof(XMM_SAVE_AREA32) + 16]; + XMM_SAVE_AREA32 *state = (XMM_SAVE_AREA32 *)(((ULONG_PTR)buffer + 15) & ~15); + + if (!has_fpux()) return; + context->ContextFlags |= CONTEXT_EXTENDED_REGISTERS; + __asm__ __volatile__( "fxsave %0" : "=m" (*state) ); + memcpy( context->ExtendedRegisters, state, sizeof(*state) ); +#endif +} + + /*********************************************************************** * restore_fpu * @@ -985,7 +1012,6 @@ static inline void save_context( CONTEXT *context, const ucontext_t *sigcontext, { context->ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS; memcpy( context->ExtendedRegisters, fpux, sizeof(*fpux) ); - fpux_support = TRUE; if (!fpu) fpux_to_fpu( &context->FloatSave, fpux ); } if (!fpu && !fpux) save_fpu( context ); @@ -1137,7 +1163,7 @@ void DECLSPEC_HIDDEN set_cpu_context( const CONTEXT *context ) { DWORD flags = context->ContextFlags & ~CONTEXT_i386; - if ((flags & CONTEXT_EXTENDED_REGISTERS) && fpux_support) restore_fpux( context ); + if ((flags & CONTEXT_EXTENDED_REGISTERS) && has_fpux()) restore_fpux( context ); else if (flags & CONTEXT_FLOATING_POINT) restore_fpu( context ); if (flags & CONTEXT_DEBUG_REGISTERS) @@ -1419,7 +1445,8 @@ NTSTATUS CDECL DECLSPEC_HIDDEN __regs_NtGetContextThread( DWORD edi, DWORD esi, context->ContextFlags |= CONTEXT_SEGMENTS; } if (needed_flags & CONTEXT_FLOATING_POINT) save_fpu( context ); - /* FIXME: extended floating point */ + if (needed_flags & CONTEXT_EXTENDED_REGISTERS) save_fpux( context ); + /* FIXME: xstate */ /* update the cached version of the debug registers */ if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)) {