ntdll: Avoid resetting x87 FPU state when saving context.

'FNSAVE' x87 instruction resets the FPU state to default values
(like FINIT). This results in FPU state reset to default in any
ntdll call which is getting x87 FPU state, e. g. obtaining context
or raising an exception.

Signed-off-by: Paul Gofman <gofmanp@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2019-03-04 16:05:16 +03:00 committed by Alexandre Julliard
parent fddea78ac1
commit c6cd92bedd
2 changed files with 19 additions and 1 deletions

View File

@ -860,8 +860,26 @@ static inline void *init_handler( const ucontext_t *sigcontext, WORD *fs, WORD *
static inline void save_fpu( CONTEXT *context )
{
#ifdef __GNUC__
struct
{
DWORD ControlWord;
DWORD StatusWord;
DWORD TagWord;
DWORD ErrorOffset;
DWORD ErrorSelector;
DWORD DataOffset;
DWORD DataSelector;
}
float_status;
context->ContextFlags |= CONTEXT_FLOATING_POINT;
__asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) );
/* Reset unmasked exceptions status to avoid firing an exception. */
memcpy(&float_status, &context->FloatSave, sizeof(float_status));
float_status.StatusWord &= float_status.ControlWord | 0xffffff80;
__asm__ __volatile__( "fldenv %0" : "=m" (float_status) );
#endif
}

View File

@ -1642,7 +1642,7 @@ static void test_thread_context(void)
ok( LOWORD(context.FloatSave.ControlWord) == LOWORD(expect.x87_control),
"wrong x87 control word %#x/%#x.\n", context.FloatSave.ControlWord, expect.x87_control );
todo_wine ok( LOWORD(expect.x87_control) == LOWORD(new_x87_control),
ok( LOWORD(expect.x87_control) == LOWORD(new_x87_control),
"x87 control word changed in NtGetContextThread() %#x/%#x.\n",
LOWORD(expect.x87_control), LOWORD(new_x87_control) );