ntdll: Store extended FPU context in NtGetContextThread().

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2019-02-14 19:46:16 +01:00
parent 5ecea50170
commit edbdec441b
1 changed files with 32 additions and 5 deletions

View File

@ -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))
{