Alexandre Julliard : ntdll: Add support for FPU registers in signal context on ARM.

Alexandre Julliard julliard at winehq.org
Wed Jul 15 16:44:45 CDT 2020


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Jul 15 10:23:34 2020 +0200

ntdll: Add support for FPU registers in signal context on ARM.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/unix/signal_arm.c | 73 +++++++++++++++++++++++++++++---------------
 1 file changed, 48 insertions(+), 25 deletions(-)

diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c
index abe47da929..1fadb0aa07 100644
--- a/dlls/ntdll/unix/signal_arm.c
+++ b/dlls/ntdll/unix/signal_arm.c
@@ -104,6 +104,48 @@ typedef struct ucontext
 # define ERROR_sig(context)         REG_sig(error_code, context)
 # define TRAP_sig(context)          REG_sig(trap_no, context)
 
+struct extended_ctx
+{
+    unsigned long magic;
+    unsigned long size;
+};
+
+struct vfp_sigframe
+{
+    struct extended_ctx ctx;
+    unsigned long long fpregs[32];
+    unsigned long fpscr;
+};
+
+static void *get_extended_sigcontext( const ucontext_t *sigcontext, unsigned int magic )
+{
+    struct extended_ctx *ctx = (struct extended_ctx *)sigcontext->uc_regspace;
+    while ((char *)ctx < (char *)(sigcontext + 1) && ctx->magic && ctx->size)
+    {
+        if (ctx->magic == magic) return ctx;
+        ctx = (struct extended_ctx *)((char *)ctx + ctx->size);
+    }
+    return NULL;
+}
+
+static void save_fpu( CONTEXT *context, const ucontext_t *sigcontext )
+{
+    struct vfp_sigframe *frame = get_extended_sigcontext( sigcontext, 0x56465001 );
+
+    if (!frame) return;
+    memcpy( context->u.D, frame->fpregs, sizeof(context->u.D) );
+    context->Fpscr = frame->fpscr;
+}
+
+static void restore_fpu( const CONTEXT *context, ucontext_t *sigcontext )
+{
+    struct vfp_sigframe *frame = get_extended_sigcontext( sigcontext, 0x56465001 );
+
+    if (!frame) return;
+    memcpy( frame->fpregs, context->u.D, sizeof(context->u.D) );
+    frame->fpscr = context->Fpscr;
+}
+
 #elif defined(__FreeBSD__)
 
 /* All Registers access - only for local access */
@@ -117,6 +159,9 @@ typedef struct ucontext
 # define IP_sig(context)            REGn_sig(_REG_R12, context)   /* Intra-Procedure-call scratch register */
 # define FP_sig(context)            REGn_sig(_REG_FP, context)    /* Frame pointer */
 
+static void save_fpu( CONTEXT *context, const ucontext_t *sigcontext ) { }
+static void restore_fpu( const CONTEXT *context, ucontext_t *sigcontext ) { }
+
 #endif /* linux */
 
 enum arm_trap_code
@@ -200,6 +245,7 @@ static void save_context( CONTEXT *context, const ucontext_t *sigcontext )
     context->Cpsr = CPSR_sig(sigcontext); /* Current State Register */
     context->R11  = FP_sig(sigcontext);   /* Frame pointer */
     context->R12  = IP_sig(sigcontext);   /* Intra-Procedure-call scratch register */
+    save_fpu( context, sigcontext );
 }
 
 
@@ -216,33 +262,12 @@ static void restore_context( const CONTEXT *context, ucontext_t *sigcontext )
 #undef C
 
     SP_sig(sigcontext)   = context->Sp;   /* Stack pointer */
-    LR_sig(sigcontext)   = context->Lr ;  /* Link register */
+    LR_sig(sigcontext)   = context->Lr;   /* Link register */
     PC_sig(sigcontext)   = context->Pc;   /* Program Counter */
     CPSR_sig(sigcontext) = context->Cpsr; /* Current State Register */
     FP_sig(sigcontext)   = context->R11;  /* Frame pointer */
     IP_sig(sigcontext)   = context->R12;  /* Intra-Procedure-call scratch register */
-}
-
-
-/***********************************************************************
- *           save_fpu
- *
- * Set the FPU context from a sigcontext.
- */
-static inline void save_fpu( CONTEXT *context, const ucontext_t *sigcontext )
-{
-    FIXME("not implemented\n");
-}
-
-
-/***********************************************************************
- *           restore_fpu
- *
- * Restore the FPU context to a sigcontext.
- */
-static inline void restore_fpu( CONTEXT *context, const ucontext_t *sigcontext )
-{
-    FIXME("not implemented\n");
+    restore_fpu( context, sigcontext );
 }
 
 
@@ -661,7 +686,6 @@ static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext )
     CONTEXT context;
     NTSTATUS status;
 
-    save_fpu( &context, sigcontext );
     save_context( &context, sigcontext );
 
     switch (siginfo->si_code & 0xffff )
@@ -716,7 +740,6 @@ static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext )
     if (status) RtlRaiseStatus( status );
 
     restore_context( &context, sigcontext );
-    restore_fpu( &context, sigcontext );
 }
 
 




More information about the wine-cvs mailing list