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

This commit is contained in:
Alexandre Julliard 2008-01-15 20:27:14 +01:00
parent bd352bcd1c
commit 992de9f487
1 changed files with 52 additions and 5 deletions

View File

@ -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);
@ -702,6 +703,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
*
@ -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 );
}