ntdll: Store FPU and XMM contexts in x86 syscall frame.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
bbae70bf1e
commit
ce5f17c892
|
@ -918,6 +918,7 @@ void signal_init_threading(void)
|
||||||
*/
|
*/
|
||||||
NTSTATUS signal_alloc_thread( TEB *teb )
|
NTSTATUS signal_alloc_thread( TEB *teb )
|
||||||
{
|
{
|
||||||
|
teb->WOW32Reserved = __wine_syscall_dispatcher;
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -461,6 +461,17 @@ enum i386_trap_code
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct syscall_xsave
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
XSAVE_FORMAT xsave;
|
||||||
|
FLOATING_SAVE_AREA fsave;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
C_ASSERT( sizeof(struct syscall_xsave) == 0x200 );
|
||||||
|
|
||||||
struct syscall_frame
|
struct syscall_frame
|
||||||
{
|
{
|
||||||
DWORD eflags; /* 00 */
|
DWORD eflags; /* 00 */
|
||||||
|
@ -502,6 +513,8 @@ C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, gs )
|
||||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, exit_frame ) == 0x1f4 );
|
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, exit_frame ) == 0x1f4 );
|
||||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, syscall_frame ) == 0x1f8 );
|
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, syscall_frame ) == 0x1f8 );
|
||||||
|
|
||||||
|
static void *syscall_dispatcher;
|
||||||
|
|
||||||
static inline struct x86_thread_data *x86_thread_data(void)
|
static inline struct x86_thread_data *x86_thread_data(void)
|
||||||
{
|
{
|
||||||
return (struct x86_thread_data *)ntdll_get_thread_data()->cpu_data;
|
return (struct x86_thread_data *)ntdll_get_thread_data()->cpu_data;
|
||||||
|
@ -2424,6 +2437,7 @@ NTSTATUS signal_alloc_thread( TEB *teb )
|
||||||
}
|
}
|
||||||
else thread_data->fs = gdt_fs_sel;
|
else thread_data->fs = gdt_fs_sel;
|
||||||
|
|
||||||
|
teb->WOW32Reserved = syscall_dispatcher;
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2501,7 +2515,14 @@ void signal_init_process(void)
|
||||||
*/
|
*/
|
||||||
void *signal_init_syscalls(void)
|
void *signal_init_syscalls(void)
|
||||||
{
|
{
|
||||||
return __wine_syscall_dispatcher;
|
extern void __wine_syscall_dispatcher_fxsave(void) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
if (cpu_info.FeatureSet & CPU_FEATURE_FXSR)
|
||||||
|
syscall_dispatcher = __wine_syscall_dispatcher_fxsave;
|
||||||
|
else
|
||||||
|
syscall_dispatcher = __wine_syscall_dispatcher;
|
||||||
|
|
||||||
|
return NtCurrentTeb()->WOW32Reserved = syscall_dispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2556,7 +2556,6 @@ static void init_teb( TEB *teb, PEB *peb )
|
||||||
PtrToUlong( &teb64->ActivationContextStack.FrameListCache );
|
PtrToUlong( &teb64->ActivationContextStack.FrameListCache );
|
||||||
teb64->StaticUnicodeString.Buffer = PtrToUlong( teb64->StaticUnicodeBuffer );
|
teb64->StaticUnicodeString.Buffer = PtrToUlong( teb64->StaticUnicodeBuffer );
|
||||||
teb64->StaticUnicodeString.MaximumLength = sizeof( teb64->StaticUnicodeBuffer );
|
teb64->StaticUnicodeString.MaximumLength = sizeof( teb64->StaticUnicodeBuffer );
|
||||||
teb->WOW32Reserved = __wine_syscall_dispatcher;
|
|
||||||
#endif
|
#endif
|
||||||
teb->Peb = peb;
|
teb->Peb = peb;
|
||||||
teb->Tib.Self = &teb->Tib;
|
teb->Tib.Self = &teb->Tib;
|
||||||
|
|
|
@ -1456,7 +1456,19 @@ static void output_syscall_dispatcher( int count, const char *variant )
|
||||||
output( "\tmovl %%ecx,-0x28(%%ebp)\n" ); /* frame->esp */
|
output( "\tmovl %%ecx,-0x28(%%ebp)\n" ); /* frame->esp */
|
||||||
output( "\tmovl 4(%%ebp),%%ecx\n" );
|
output( "\tmovl 4(%%ebp),%%ecx\n" );
|
||||||
output( "\tmovl %%ecx,-0x2c(%%ebp)\n" ); /* frame->eip */
|
output( "\tmovl %%ecx,-0x2c(%%ebp)\n" ); /* frame->eip */
|
||||||
output( "\tmovl %%esp,%%fs:0x1f8\n" ); /* x86_thread_data()->syscall_frame */
|
output( "\tsubl $0x200,%%esp\n") ;
|
||||||
|
output( "\tandl $~63,%%esp\n" );
|
||||||
|
if (!*variant)
|
||||||
|
{
|
||||||
|
output( "\tfnsave (%%esp)\n" );
|
||||||
|
output( "\tfwait\n" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output( "\tfxsave (%%esp)\n" );
|
||||||
|
}
|
||||||
|
output( "\tleal -0x30(%%ebp),%%ecx\n" );
|
||||||
|
output( "\tmovl %%ecx,%%fs:0x1f8\n" ); /* x86_thread_data()->syscall_frame */
|
||||||
output( "\tcmpl $%u,%%eax\n", count );
|
output( "\tcmpl $%u,%%eax\n", count );
|
||||||
output( "\tjae 4f\n" );
|
output( "\tjae 4f\n" );
|
||||||
if (UsePIC)
|
if (UsePIC)
|
||||||
|
@ -1479,6 +1491,17 @@ static void output_syscall_dispatcher( int count, const char *variant )
|
||||||
else
|
else
|
||||||
output( "\tcall *.Lsyscall_table(,%%eax,4)\n" );
|
output( "\tcall *.Lsyscall_table(,%%eax,4)\n" );
|
||||||
output( "2:\tmovl $0,%%fs:0x1f8\n" );
|
output( "2:\tmovl $0,%%fs:0x1f8\n" );
|
||||||
|
output( "\tleal -0x230(%%ebp),%%ebx\n") ;
|
||||||
|
output( "\tandl $~63,%%ebx\n" );
|
||||||
|
if (!*variant)
|
||||||
|
{
|
||||||
|
output( "\tfrstor (%%ebx)\n" );
|
||||||
|
output( "\tfwait\n" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output( "\tfxrstor (%%ebx)\n" );
|
||||||
|
}
|
||||||
output( "\tleal -0x30(%%ebp),%%ebx\n" );
|
output( "\tleal -0x30(%%ebp),%%ebx\n" );
|
||||||
output_cfi( ".cfi_def_cfa_register %%ebx" );
|
output_cfi( ".cfi_def_cfa_register %%ebx" );
|
||||||
output_cfi( ".cfi_adjust_cfa_offset 0x30\n" );
|
output_cfi( ".cfi_adjust_cfa_offset 0x30\n" );
|
||||||
|
@ -1792,6 +1815,9 @@ void output_syscalls( DLLSPEC *spec )
|
||||||
|
|
||||||
switch( target_cpu )
|
switch( target_cpu )
|
||||||
{
|
{
|
||||||
|
case CPU_x86:
|
||||||
|
output_syscall_dispatcher( count, "_fxsave" );
|
||||||
|
break;
|
||||||
case CPU_x86_64:
|
case CPU_x86_64:
|
||||||
output_syscall_dispatcher( count, "_xsave" );
|
output_syscall_dispatcher( count, "_xsave" );
|
||||||
output_syscall_dispatcher( count, "_xsavec" );
|
output_syscall_dispatcher( count, "_xsavec" );
|
||||||
|
|
Loading…
Reference in New Issue