Commit f30ba2cf authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent 99851ca4
...@@ -104,6 +104,48 @@ typedef struct ucontext ...@@ -104,6 +104,48 @@ typedef struct ucontext
# define ERROR_sig(context) REG_sig(error_code, context) # define ERROR_sig(context) REG_sig(error_code, context)
# define TRAP_sig(context) REG_sig(trap_no, 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__) #elif defined(__FreeBSD__)
/* All Registers access - only for local access */ /* All Registers access - only for local access */
...@@ -117,6 +159,9 @@ typedef struct ucontext ...@@ -117,6 +159,9 @@ typedef struct ucontext
# define IP_sig(context) REGn_sig(_REG_R12, context) /* Intra-Procedure-call scratch register */ # 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 */ # 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 */ #endif /* linux */
enum arm_trap_code enum arm_trap_code
...@@ -200,6 +245,7 @@ static void save_context( CONTEXT *context, const ucontext_t *sigcontext ) ...@@ -200,6 +245,7 @@ static void save_context( CONTEXT *context, const ucontext_t *sigcontext )
context->Cpsr = CPSR_sig(sigcontext); /* Current State Register */ context->Cpsr = CPSR_sig(sigcontext); /* Current State Register */
context->R11 = FP_sig(sigcontext); /* Frame pointer */ context->R11 = FP_sig(sigcontext); /* Frame pointer */
context->R12 = IP_sig(sigcontext); /* Intra-Procedure-call scratch register */ 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 ) ...@@ -216,33 +262,12 @@ static void restore_context( const CONTEXT *context, ucontext_t *sigcontext )
#undef C #undef C
SP_sig(sigcontext) = context->Sp; /* Stack pointer */ 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 */ PC_sig(sigcontext) = context->Pc; /* Program Counter */
CPSR_sig(sigcontext) = context->Cpsr; /* Current State Register */ CPSR_sig(sigcontext) = context->Cpsr; /* Current State Register */
FP_sig(sigcontext) = context->R11; /* Frame pointer */ FP_sig(sigcontext) = context->R11; /* Frame pointer */
IP_sig(sigcontext) = context->R12; /* Intra-Procedure-call scratch register */ IP_sig(sigcontext) = context->R12; /* Intra-Procedure-call scratch register */
} restore_fpu( context, sigcontext );
/***********************************************************************
* 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");
} }
...@@ -661,7 +686,6 @@ static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext ) ...@@ -661,7 +686,6 @@ static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext )
CONTEXT context; CONTEXT context;
NTSTATUS status; NTSTATUS status;
save_fpu( &context, sigcontext );
save_context( &context, sigcontext ); save_context( &context, sigcontext );
switch (siginfo->si_code & 0xffff ) switch (siginfo->si_code & 0xffff )
...@@ -716,7 +740,6 @@ static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext ) ...@@ -716,7 +740,6 @@ static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext )
if (status) RtlRaiseStatus( status ); if (status) RtlRaiseStatus( status );
restore_context( &context, sigcontext ); restore_context( &context, sigcontext );
restore_fpu( &context, sigcontext );
} }
......
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