Paul Gofman : ntdll: Avoid resetting x87 FPU state when saving context.

Alexandre Julliard julliard at winehq.org
Mon Mar 4 15:08:25 CST 2019


Module: wine
Branch: master
Commit: c6cd92bedda4296ce3e666e28c470a5c4b618fee
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=c6cd92bedda4296ce3e666e28c470a5c4b618fee

Author: Paul Gofman <gofmanp at gmail.com>
Date:   Mon Mar  4 16:05:16 2019 +0300

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 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/signal_i386.c     | 18 ++++++++++++++++++
 dlls/ntdll/tests/exception.c |  2 +-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 0274a7d..f1deb1c 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -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
 }
 
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index f1a59f1..57ad30f 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -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) );
 




More information about the wine-cvs mailing list