Commit c6cd92be authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

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: 's avatarPaul Gofman <gofmanp@gmail.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent fddea78a
...@@ -860,8 +860,26 @@ static inline void *init_handler( const ucontext_t *sigcontext, WORD *fs, WORD * ...@@ -860,8 +860,26 @@ static inline void *init_handler( const ucontext_t *sigcontext, WORD *fs, WORD *
static inline void save_fpu( CONTEXT *context ) static inline void save_fpu( CONTEXT *context )
{ {
#ifdef __GNUC__ #ifdef __GNUC__
struct
{
DWORD ControlWord;
DWORD StatusWord;
DWORD TagWord;
DWORD ErrorOffset;
DWORD ErrorSelector;
DWORD DataOffset;
DWORD DataSelector;
}
float_status;
context->ContextFlags |= CONTEXT_FLOATING_POINT; context->ContextFlags |= CONTEXT_FLOATING_POINT;
__asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) ); __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 #endif
} }
......
...@@ -1642,7 +1642,7 @@ static void test_thread_context(void) ...@@ -1642,7 +1642,7 @@ static void test_thread_context(void)
ok( LOWORD(context.FloatSave.ControlWord) == LOWORD(expect.x87_control), ok( LOWORD(context.FloatSave.ControlWord) == LOWORD(expect.x87_control),
"wrong x87 control word %#x/%#x.\n", context.FloatSave.ControlWord, 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", "x87 control word changed in NtGetContextThread() %#x/%#x.\n",
LOWORD(expect.x87_control), LOWORD(new_x87_control) ); LOWORD(expect.x87_control), LOWORD(new_x87_control) );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment