Alexandre Julliard : ntdll: Mac OS support for saving and restoring the extended FPU context on exceptions .

Alexandre Julliard julliard at winehq.org
Wed Jan 16 07:09:31 CST 2008


Module: wine
Branch: master
Commit: 992de9f487abf009e027ce51c51f94961573bf34
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=992de9f487abf009e027ce51c51f94961573bf34

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Jan 15 20:27:14 2008 +0100

ntdll: Mac OS support for saving and restoring the extended FPU context on exceptions.

---

 dlls/ntdll/signal_i386.c |   57 +++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index b07715c..03729ed 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -304,6 +304,8 @@ typedef ucontext_t SIGCONTEXT;
 #define ESP_sig(context)     (*((unsigned long*)&(context)->uc_mcontext->__ss.__esp))
 #define TRAP_sig(context)    ((context)->uc_mcontext->__es.__trapno)
 #define ERROR_sig(context)   ((context)->uc_mcontext->__es.__err)
+#define FPU_sig(context)     NULL
+#define FPUX_sig(context)    ((XMM_SAVE_AREA32 *)&(context)->uc_mcontext->__fs.__fpu_fcw)
 #else
 #define EAX_sig(context)     ((context)->uc_mcontext->ss.eax)
 #define EBX_sig(context)     ((context)->uc_mcontext->ss.ebx)
@@ -323,11 +325,10 @@ typedef ucontext_t SIGCONTEXT;
 #define ESP_sig(context)     (*((unsigned long*)&(context)->uc_mcontext->ss.esp))
 #define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
 #define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
+#define FPU_sig(context)     NULL
+#define FPUX_sig(context)    ((XMM_SAVE_AREA32 *)&(context)->uc_mcontext->fs.fpu_fcw)
 #endif
 
-#define FPU_sig(context)     NULL  /* FIXME */
-#define FPUX_sig(context)    NULL  /* FIXME */
-
 #endif /* __APPLE__ */
 
 WINE_DEFAULT_DEBUG_CHANNEL(seh);
@@ -703,6 +704,52 @@ static inline void restore_fpux( const CONTEXT *context )
 
 
 /***********************************************************************
+ *           fpux_to_fpu
+ *
+ * Build a standard FPU context from an extended one.
+ */
+static void fpux_to_fpu( FLOATING_SAVE_AREA *fpu, const XMM_SAVE_AREA32 *fpux )
+{
+    unsigned int i, tag, stack_top;
+
+    fpu->ControlWord   = fpux->ControlWord | 0xffff0000;
+    fpu->StatusWord    = fpux->StatusWord | 0xffff0000;
+    fpu->ErrorOffset   = fpux->ErrorOffset;
+    fpu->ErrorSelector = fpux->ErrorSelector | (fpux->ErrorOpcode << 16);
+    fpu->DataOffset    = fpux->DataOffset;
+    fpu->DataSelector  = fpux->DataSelector;
+    fpu->Cr0NpxState   = fpux->StatusWord | 0xffff0000;
+
+    stack_top = (fpux->StatusWord >> 11) & 7;
+    fpu->TagWord = 0xffff0000;
+    for (i = 0; i < 8; i++)
+    {
+        memcpy( &fpu->RegisterArea[10 * i], &fpux->FloatRegisters[i], 10 );
+        if (!(fpux->TagWord & (1 << i))) tag = 3;  /* empty */
+        else
+        {
+            const M128A *reg = &fpux->FloatRegisters[(i - stack_top) & 7];
+            if ((reg->High & 0x7fff) == 0x7fff)  /* exponent all ones */
+            {
+                tag = 2;  /* special */
+            }
+            else if (!(reg->High & 0x7fff))  /* exponent all zeroes */
+            {
+                if (reg->Low) tag = 2;  /* special */
+                else tag = 1;  /* zero */
+            }
+            else
+            {
+                if (reg->Low >> 63) tag = 0;  /* valid */
+                else tag = 2;  /* special */
+            }
+        }
+        fpu->TagWord |= tag << (2 * i);
+    }
+}
+
+
+/***********************************************************************
  *           save_context
  *
  * Build a context structure from the signal info.
@@ -746,10 +793,10 @@ static inline void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext,
     if (fpux)
     {
         save_fpux( context );
-        context->ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
+        context->ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
         memcpy( context->ExtendedRegisters, fpux, sizeof(*fpux) );
         fpux_support = 1;
-        /* FIXME: convert fpux to fpu */
+        if (!fpu) fpux_to_fpu( &context->FloatSave, fpux );
     }
     if (!fpu && !fpux) save_fpu( context );
 }




More information about the wine-cvs mailing list