ntdll: Add support for FPU registers in signal context on ARM.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
99851ca4c2
commit
f30ba2cf25
|
@ -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
|
||||||
# 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 )
|
||||||
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 )
|
||||||
#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 )
|
||||||
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 )
|
||||||
if (status) RtlRaiseStatus( status );
|
if (status) RtlRaiseStatus( status );
|
||||||
|
|
||||||
restore_context( &context, sigcontext );
|
restore_context( &context, sigcontext );
|
||||||
restore_fpu( &context, sigcontext );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue