ntdll: Go through the syscall return path for syscall faults.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
5b47e4ac0b
commit
db26df5934
|
@ -600,19 +600,9 @@ static BOOL handle_syscall_fault( ucontext_t *context, EXCEPTION_RECORD *rec )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACE( "returning to user mode ip=%08x ret=%08x\n", frame->pc, rec->ExceptionCode );
|
TRACE( "returning to user mode ip=%08x ret=%08x\n", frame->pc, rec->ExceptionCode );
|
||||||
REGn_sig(0, context) = rec->ExceptionCode;
|
REGn_sig(0, context) = (DWORD)frame;
|
||||||
REGn_sig(4, context) = frame->r4;
|
REGn_sig(1, context) = rec->ExceptionCode;
|
||||||
REGn_sig(5, context) = frame->r5;
|
PC_sig(context) = (DWORD)__wine_syscall_dispatcher_return;
|
||||||
REGn_sig(6, context) = frame->r6;
|
|
||||||
REGn_sig(7, context) = frame->r7;
|
|
||||||
REGn_sig(8, context) = frame->r8;
|
|
||||||
REGn_sig(9, context) = frame->r9;
|
|
||||||
REGn_sig(10, context) = frame->r10;
|
|
||||||
FP_sig(context) = frame->r11;
|
|
||||||
LR_sig(context) = frame->lr;
|
|
||||||
SP_sig(context) = frame->sp;
|
|
||||||
PC_sig(context) = frame->pc;
|
|
||||||
CPSR_sig(context) = frame->cpsr;
|
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -756,12 +756,9 @@ static BOOL handle_syscall_fault( ucontext_t *context, EXCEPTION_RECORD *rec )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACE( "returning to user mode ip=%p ret=%08x\n", (void *)frame->pc, rec->ExceptionCode );
|
TRACE( "returning to user mode ip=%p ret=%08x\n", (void *)frame->pc, rec->ExceptionCode );
|
||||||
for (i = 18; i < 29; i++) REGn_sig( i, context ) = frame->x[i];
|
REGn_sig(0, context) = (ULONG_PTR)frame;
|
||||||
REGn_sig(0, context) = rec->ExceptionCode;
|
REGn_sig(1, context) = rec->ExceptionCode;
|
||||||
FP_sig(context) = frame->fp;
|
PC_sig(context) = (ULONG_PTR)__wine_syscall_dispatcher_return;
|
||||||
LR_sig(context) = frame->lr;
|
|
||||||
SP_sig(context) = frame->sp;
|
|
||||||
PC_sig(context) = frame->pc;
|
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -480,7 +480,8 @@ struct syscall_frame
|
||||||
DWORD edi; /* 02c */
|
DWORD edi; /* 02c */
|
||||||
DWORD esi; /* 030 */
|
DWORD esi; /* 030 */
|
||||||
DWORD ebp; /* 034 */
|
DWORD ebp; /* 034 */
|
||||||
DWORD align[2]; /* 038 */
|
DWORD syscall_flags; /* 038 */
|
||||||
|
DWORD align; /* 03c */
|
||||||
union /* 040 */
|
union /* 040 */
|
||||||
{
|
{
|
||||||
XSAVE_FORMAT xsave;
|
XSAVE_FORMAT xsave;
|
||||||
|
@ -1709,7 +1710,7 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, void *stack_ptr,
|
||||||
EXCEPTION_RECORD *rec, CONTEXT *context )
|
EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||||
{
|
{
|
||||||
struct syscall_frame *frame = x86_thread_data()->syscall_frame;
|
struct syscall_frame *frame = x86_thread_data()->syscall_frame;
|
||||||
DWORD i;
|
DWORD i, *stack;
|
||||||
|
|
||||||
if (!is_inside_syscall( sigcontext )) return FALSE;
|
if (!is_inside_syscall( sigcontext )) return FALSE;
|
||||||
|
|
||||||
|
@ -1727,10 +1728,9 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, void *stack_ptr,
|
||||||
|
|
||||||
if (ntdll_get_thread_data()->jmp_buf)
|
if (ntdll_get_thread_data()->jmp_buf)
|
||||||
{
|
{
|
||||||
DWORD *stack = stack_ptr;
|
|
||||||
|
|
||||||
TRACE( "returning to handler\n" );
|
TRACE( "returning to handler\n" );
|
||||||
/* push stack frame for calling __wine_longjmp */
|
/* push stack frame for calling __wine_longjmp */
|
||||||
|
stack = stack_ptr;
|
||||||
*(--stack) = 1;
|
*(--stack) = 1;
|
||||||
*(--stack) = (DWORD)ntdll_get_thread_data()->jmp_buf;
|
*(--stack) = (DWORD)ntdll_get_thread_data()->jmp_buf;
|
||||||
*(--stack) = 0xdeadbabe; /* return address */
|
*(--stack) = 0xdeadbabe; /* return address */
|
||||||
|
@ -1741,13 +1741,12 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, void *stack_ptr,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACE( "returning to user mode ip=%08x ret=%08x\n", frame->eip, rec->ExceptionCode );
|
TRACE( "returning to user mode ip=%08x ret=%08x\n", frame->eip, rec->ExceptionCode );
|
||||||
EAX_sig(sigcontext) = rec->ExceptionCode;
|
stack = (DWORD *)frame;
|
||||||
EBX_sig(sigcontext) = frame->ebx;
|
*(--stack) = rec->ExceptionCode;
|
||||||
ESI_sig(sigcontext) = frame->esi;
|
*(--stack) = (DWORD)frame;
|
||||||
EDI_sig(sigcontext) = frame->edi;
|
*(--stack) = 0xdeadbabe; /* return address */
|
||||||
EBP_sig(sigcontext) = frame->ebp;
|
ESP_sig(sigcontext) = (DWORD)stack;
|
||||||
ESP_sig(sigcontext) = frame->esp;
|
EIP_sig(sigcontext) = (DWORD)__wine_syscall_dispatcher_return;
|
||||||
EIP_sig(sigcontext) = frame->eip;
|
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -2401,6 +2400,8 @@ static void init_thread_context( CONTEXT *context, LPTHREAD_START_ROUTINE entry,
|
||||||
*/
|
*/
|
||||||
PCONTEXT DECLSPEC_HIDDEN get_initial_context( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, TEB *teb )
|
PCONTEXT DECLSPEC_HIDDEN get_initial_context( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, TEB *teb )
|
||||||
{
|
{
|
||||||
|
struct x86_thread_data *thread_data = (struct x86_thread_data *)&teb->GdiTebBatch;
|
||||||
|
struct syscall_frame *frame = thread_data->syscall_frame;
|
||||||
CONTEXT *ctx;
|
CONTEXT *ctx;
|
||||||
|
|
||||||
if (suspend)
|
if (suspend)
|
||||||
|
@ -2417,6 +2418,7 @@ PCONTEXT DECLSPEC_HIDDEN get_initial_context( LPTHREAD_START_ROUTINE entry, void
|
||||||
ctx = (CONTEXT *)((char *)teb->Tib.StackBase - 16) - 1;
|
ctx = (CONTEXT *)((char *)teb->Tib.StackBase - 16) - 1;
|
||||||
init_thread_context( ctx, entry, arg, teb );
|
init_thread_context( ctx, entry, arg, teb );
|
||||||
}
|
}
|
||||||
|
frame->syscall_flags = __wine_syscall_flags;
|
||||||
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
|
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
|
||||||
ctx->ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
|
ctx->ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
|
||||||
return ctx;
|
return ctx;
|
||||||
|
|
|
@ -2182,21 +2182,10 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, EXCEPTION_RECORD *rec,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
XMM_SAVE_AREA32 *fpu = FPU_sig(sigcontext);
|
|
||||||
|
|
||||||
TRACE( "returning to user mode ip=%016lx ret=%08x\n", frame->rip, rec->ExceptionCode );
|
TRACE( "returning to user mode ip=%016lx ret=%08x\n", frame->rip, rec->ExceptionCode );
|
||||||
RAX_sig(sigcontext) = rec->ExceptionCode;
|
RCX_sig(sigcontext) = (ULONG_PTR)frame;
|
||||||
RBX_sig(sigcontext) = frame->rbx;
|
RDX_sig(sigcontext) = rec->ExceptionCode;
|
||||||
RSI_sig(sigcontext) = frame->rsi;
|
RIP_sig(sigcontext) = (ULONG_PTR)__wine_syscall_dispatcher_return;
|
||||||
RDI_sig(sigcontext) = frame->rdi;
|
|
||||||
RBP_sig(sigcontext) = frame->rbp;
|
|
||||||
R12_sig(sigcontext) = frame->r12;
|
|
||||||
R13_sig(sigcontext) = frame->r13;
|
|
||||||
R14_sig(sigcontext) = frame->r14;
|
|
||||||
R15_sig(sigcontext) = frame->r15;
|
|
||||||
RSP_sig(sigcontext) = frame->rsp;
|
|
||||||
RIP_sig(sigcontext) = frame->rip;
|
|
||||||
if (fpu) *fpu = frame->xsave;
|
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,6 +239,7 @@ extern void DECLSPEC_NORETURN signal_start_thread( PRTL_THREAD_START_ROUTINE ent
|
||||||
BOOL suspend, void *thunk, TEB *teb ) DECLSPEC_HIDDEN;
|
BOOL suspend, void *thunk, TEB *teb ) DECLSPEC_HIDDEN;
|
||||||
extern void DECLSPEC_NORETURN signal_exit_thread( int status, void (*func)(int), TEB *teb ) DECLSPEC_HIDDEN;
|
extern void DECLSPEC_NORETURN signal_exit_thread( int status, void (*func)(int), TEB *teb ) DECLSPEC_HIDDEN;
|
||||||
extern void __wine_syscall_dispatcher(void) DECLSPEC_HIDDEN;
|
extern void __wine_syscall_dispatcher(void) DECLSPEC_HIDDEN;
|
||||||
|
extern void WINAPI DECLSPEC_NORETURN __wine_syscall_dispatcher_return( void *frame, ULONG_PTR retval ) DECLSPEC_HIDDEN;
|
||||||
extern unsigned int __wine_syscall_flags DECLSPEC_HIDDEN;
|
extern unsigned int __wine_syscall_flags DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS signal_set_full_context( CONTEXT *context ) DECLSPEC_HIDDEN;
|
extern NTSTATUS signal_set_full_context( CONTEXT *context ) DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS get_thread_wow64_context( HANDLE handle, void *ctx, ULONG size ) DECLSPEC_HIDDEN;
|
extern NTSTATUS get_thread_wow64_context( HANDLE handle, void *ctx, ULONG size ) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -1460,27 +1460,22 @@ static void output_syscall_dispatcher(void)
|
||||||
{
|
{
|
||||||
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||||
output( "1:\tleal %s-1b(%%eax,%%edx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
|
output( "1:\tleal %s-1b(%%eax,%%edx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
|
||||||
output( "\tmovl %s-1b(%%eax),%%edi\n", asm_name("__wine_syscall_flags") );
|
|
||||||
needs_get_pc_thunk = 1;
|
needs_get_pc_thunk = 1;
|
||||||
}
|
}
|
||||||
else
|
else output( "\tleal %s(%%edx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
|
||||||
{
|
output( "\ttestl $3,0x38(%%ecx)\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||||
output( "\tleal %s(%%edx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
|
|
||||||
output( "\tmovl %s,%%edi\n", asm_name("__wine_syscall_flags") );
|
|
||||||
}
|
|
||||||
output( "\ttestl $3,%%edi\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
|
||||||
output( "\tjz 2f\n" );
|
output( "\tjz 2f\n" );
|
||||||
output( "\tmovl $7,%%eax\n" );
|
output( "\tmovl $7,%%eax\n" );
|
||||||
output( "\txorl %%edx,%%edx\n" );
|
output( "\txorl %%edx,%%edx\n" );
|
||||||
for (i = 0; i < 6; i++) output( "\tmovl %%edx,0x%x(%%ecx)\n", 0x240 + i * 4 );
|
for (i = 0; i < 6; i++) output( "\tmovl %%edx,0x%x(%%ecx)\n", 0x240 + i * 4 );
|
||||||
output( "\ttestl $2,%%edi\n" ); /* SYSCALL_HAVE_XSAVEC */
|
output( "\ttestl $2,0x38(%%ecx)\n" ); /* SYSCALL_HAVE_XSAVEC */
|
||||||
output( "\tjz 1f\n" );
|
output( "\tjz 1f\n" );
|
||||||
for (i = 6; i < 16; i++) output( "\tmovl %%edx,0x%x(%%ecx)\n", 0x240 + i * 4 );
|
for (i = 6; i < 16; i++) output( "\tmovl %%edx,0x%x(%%ecx)\n", 0x240 + i * 4 );
|
||||||
output( "\txsavec 0x40(%%ecx)\n" );
|
output( "\txsavec 0x40(%%ecx)\n" );
|
||||||
output( "\tjmp 4f\n" );
|
output( "\tjmp 4f\n" );
|
||||||
output( "1:\txsave 0x40(%%ecx)\n" );
|
output( "1:\txsave 0x40(%%ecx)\n" );
|
||||||
output( "\tjmp 4f\n" );
|
output( "\tjmp 4f\n" );
|
||||||
output( "2:\ttestl $4,%%edi\n" ); /* SYSCALL_HAVE_FXSAVE */
|
output( "2:\ttestl $4,0x38(%%ecx)\n" ); /* SYSCALL_HAVE_FXSAVE */
|
||||||
output( "\tjz 3f\n" );
|
output( "\tjz 3f\n" );
|
||||||
output( "\tfxsave 0x40(%%ecx)\n" );
|
output( "\tfxsave 0x40(%%ecx)\n" );
|
||||||
output( "\tjmp 4f\n" );
|
output( "\tjmp 4f\n" );
|
||||||
|
@ -1494,20 +1489,18 @@ static void output_syscall_dispatcher(void)
|
||||||
output( "\tmovl 12(%%ebx),%%eax\n" ); /* table->ArgumentTable */
|
output( "\tmovl 12(%%ebx),%%eax\n" ); /* table->ArgumentTable */
|
||||||
output( "\tmovzbl (%%eax,%%edx,1),%%ecx\n" );
|
output( "\tmovzbl (%%eax,%%edx,1),%%ecx\n" );
|
||||||
output( "\tmovl (%%ebx),%%eax\n" ); /* table->ServiceTable */
|
output( "\tmovl (%%ebx),%%eax\n" ); /* table->ServiceTable */
|
||||||
output( "\tmovl %%edi,%%ebx\n" );
|
|
||||||
output( "\tsubl %%ecx,%%esp\n" );
|
output( "\tsubl %%ecx,%%esp\n" );
|
||||||
output( "\tshrl $2,%%ecx\n" );
|
output( "\tshrl $2,%%ecx\n" );
|
||||||
output( "\tandl $~15,%%esp\n" );
|
output( "\tandl $~15,%%esp\n" );
|
||||||
output( "\tmovl %%esp,%%edi\n" );
|
output( "\tmovl %%esp,%%edi\n" );
|
||||||
output( "\tcld\n" );
|
output( "\tcld\n" );
|
||||||
output( "\trep; movsl\n" );
|
output( "\trep; movsl\n" );
|
||||||
output( "\tmovl %%ebx,%%edi\n" );
|
|
||||||
output( "\tcall *(%%eax,%%edx,4)\n" );
|
output( "\tcall *(%%eax,%%edx,4)\n" );
|
||||||
output( "5:\tleal -0x34(%%ebp),%%esp\n" );
|
output( "\tleal -0x34(%%ebp),%%esp\n" );
|
||||||
output( "\tmovl (%%esp),%%ecx\n" ); /* frame->restore_flags */
|
output( "5:\tmovl (%%esp),%%ecx\n" ); /* frame->restore_flags */
|
||||||
output( "\ttestl $0x68,%%ecx\n" ); /* CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS | CONTEXT_XSAVE */
|
output( "\ttestl $0x68,%%ecx\n" ); /* CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS | CONTEXT_XSAVE */
|
||||||
output( "\tjz 3f\n" );
|
output( "\tjz 3f\n" );
|
||||||
output( "\ttestl $3,%%edi\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
output( "\ttestl $3,0x38(%%esp)\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||||
output( "\tjz 1f\n" );
|
output( "\tjz 1f\n" );
|
||||||
output( "\tmovl %%eax,%%esi\n" );
|
output( "\tmovl %%eax,%%esi\n" );
|
||||||
output( "\tmovl $7,%%eax\n" );
|
output( "\tmovl $7,%%eax\n" );
|
||||||
|
@ -1515,7 +1508,7 @@ static void output_syscall_dispatcher(void)
|
||||||
output( "\txrstor 0x40(%%esp)\n" );
|
output( "\txrstor 0x40(%%esp)\n" );
|
||||||
output( "\tmovl %%esi,%%eax\n" );
|
output( "\tmovl %%esi,%%eax\n" );
|
||||||
output( "\tjmp 3f\n" );
|
output( "\tjmp 3f\n" );
|
||||||
output( "1:\ttestl $4,%%edi\n" ); /* SYSCALL_HAVE_FXSAVE */
|
output( "1:\ttestl $4,0x38(%%esp)\n" ); /* SYSCALL_HAVE_FXSAVE */
|
||||||
output( "\tjz 2f\n" );
|
output( "\tjz 2f\n" );
|
||||||
output( "\tfxrstor 0x40(%%esp)\n" );
|
output( "\tfxrstor 0x40(%%esp)\n" );
|
||||||
output( "\tjmp 3f\n" );
|
output( "\tjmp 3f\n" );
|
||||||
|
@ -1550,6 +1543,10 @@ static void output_syscall_dispatcher(void)
|
||||||
output( "\tiret\n" );
|
output( "\tiret\n" );
|
||||||
output( "6:\tmovl $0x%x,%%eax\n", invalid_param );
|
output( "6:\tmovl $0x%x,%%eax\n", invalid_param );
|
||||||
output( "\tjmp 5b\n" );
|
output( "\tjmp 5b\n" );
|
||||||
|
output( "%s\n", asm_globl("__wine_syscall_dispatcher_return") );
|
||||||
|
output( "\tmovl 8(%%esp),%%eax\n" );
|
||||||
|
output( "\tmovl 4(%%esp),%%esp\n" );
|
||||||
|
output( "\tjmp 5b\n" );
|
||||||
break;
|
break;
|
||||||
case CPU_x86_64:
|
case CPU_x86_64:
|
||||||
output( "\tmovq %%gs:0x30,%%rcx\n" );
|
output( "\tmovq %%gs:0x30,%%rcx\n" );
|
||||||
|
@ -1626,8 +1623,8 @@ static void output_syscall_dispatcher(void)
|
||||||
output( "\tsubq $0x20,%%rsp\n" );
|
output( "\tsubq $0x20,%%rsp\n" );
|
||||||
output( "\tmovq (%%rbx),%%r10\n" ); /* table->ServiceTable */
|
output( "\tmovq (%%rbx),%%r10\n" ); /* table->ServiceTable */
|
||||||
output( "\tcallq *(%%r10,%%rax,8)\n" );
|
output( "\tcallq *(%%r10,%%rax,8)\n" );
|
||||||
output( "2:\tleaq -0x98(%%rbp),%%rcx\n" );
|
output( "\tleaq -0x98(%%rbp),%%rcx\n" );
|
||||||
output( "\tmovl 0x94(%%rcx),%%edx\n" ); /* frame->restore_flags */
|
output( "2:\tmovl 0x94(%%rcx),%%edx\n" ); /* frame->restore_flags */
|
||||||
output( "\ttestl $0x48,%%edx\n" ); /* CONTEXT_FLOATING_POINT | CONTEXT_XSTATE */
|
output( "\ttestl $0x48,%%edx\n" ); /* CONTEXT_FLOATING_POINT | CONTEXT_XSTATE */
|
||||||
output( "\tjz 4f\n" );
|
output( "\tjz 4f\n" );
|
||||||
output( "\ttestl $3,%%r14d\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
output( "\ttestl $3,%%r14d\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||||
|
@ -1663,7 +1660,11 @@ static void output_syscall_dispatcher(void)
|
||||||
output( "\tmovq 0x48(%%rcx),%%r11\n" );
|
output( "\tmovq 0x48(%%rcx),%%r11\n" );
|
||||||
output( "\tmovq 0x10(%%rcx),%%rcx\n" );
|
output( "\tmovq 0x10(%%rcx),%%rcx\n" );
|
||||||
output( "1:\tiretq\n" );
|
output( "1:\tiretq\n" );
|
||||||
output( "5:\tmovl $0x%x,%%eax\n", invalid_param );
|
output( "5:\tmovl $0x%x,%%edx\n", invalid_param );
|
||||||
|
output( "\tmovq %%rsp,%%rcx\n" );
|
||||||
|
output( "%s\n", asm_globl("__wine_syscall_dispatcher_return") );
|
||||||
|
output( "\tmovl %s(%%rip),%%r14d\n", asm_name("__wine_syscall_flags") );
|
||||||
|
output( "\tmovq %%rdx,%%rax\n" );
|
||||||
output( "\tjmp 2b\n" );
|
output( "\tjmp 2b\n" );
|
||||||
break;
|
break;
|
||||||
case CPU_ARM:
|
case CPU_ARM:
|
||||||
|
@ -1712,7 +1713,7 @@ static void output_syscall_dispatcher(void)
|
||||||
output( "\tldr r5, [r4]\n"); /* table->ServiceTable */
|
output( "\tldr r5, [r4]\n"); /* table->ServiceTable */
|
||||||
output( "\tldr ip, [r5, ip, lsl #2]\n");
|
output( "\tldr ip, [r5, ip, lsl #2]\n");
|
||||||
output( "\tblx ip\n");
|
output( "\tblx ip\n");
|
||||||
output( "\tldr ip, [r8, #0x44]\n" ); /* frame->restore_flags */
|
output( "4:\tldr ip, [r8, #0x44]\n" ); /* frame->restore_flags */
|
||||||
if (strcmp( float_abi_option, "soft" ))
|
if (strcmp( float_abi_option, "soft" ))
|
||||||
{
|
{
|
||||||
output( "\ttst ip, #4\n" ); /* CONTEXT_FLOATING_POINT */
|
output( "\ttst ip, #4\n" ); /* CONTEXT_FLOATING_POINT */
|
||||||
|
@ -1726,13 +1727,17 @@ static void output_syscall_dispatcher(void)
|
||||||
output( "\ttst ip, #2\n" ); /* CONTEXT_INTEGER */
|
output( "\ttst ip, #2\n" ); /* CONTEXT_INTEGER */
|
||||||
output( "\tit ne\n" );
|
output( "\tit ne\n" );
|
||||||
output( "\tldmne r8, {r0-r3}\n" );
|
output( "\tldmne r8, {r0-r3}\n" );
|
||||||
output( "4:\tldr lr, [r8, #0x3c]\n" );
|
output( "\tldr lr, [r8, #0x3c]\n" );
|
||||||
output( "\tldr sp, [r8, #0x38]\n" );
|
output( "\tldr sp, [r8, #0x38]\n" );
|
||||||
output( "\tadd r8, r8, #0x10\n" );
|
output( "\tadd r8, r8, #0x10\n" );
|
||||||
output( "\tldm r8, {r4-r12,pc}\n" );
|
output( "\tldm r8, {r4-r12,pc}\n" );
|
||||||
output( "5:\tmovw r0, #0x%x\n", invalid_param & 0xffff );
|
output( "5:\tmovw r0, #0x%x\n", invalid_param & 0xffff );
|
||||||
output( "\tmovt r0, #0x%x\n", invalid_param >> 16 );
|
output( "\tmovt r0, #0x%x\n", invalid_param >> 16 );
|
||||||
output( "\tb 4b\n" );
|
output( "\tb 4b\n" );
|
||||||
|
output( "%s\n", asm_globl("__wine_syscall_dispatcher_return") );
|
||||||
|
output( "\tmov r8, r0\n" );
|
||||||
|
output( "\tmov r0, r1\n" );
|
||||||
|
output( "\tb 4b\n" );
|
||||||
if (UsePIC)
|
if (UsePIC)
|
||||||
output( "6:\t.long %s-1b-%u\n", asm_name("KeServiceDescriptorTable"), thumb_mode ? 4 : 8 );
|
output( "6:\t.long %s-1b-%u\n", asm_name("KeServiceDescriptorTable"), thumb_mode ? 4 : 8 );
|
||||||
else
|
else
|
||||||
|
@ -1836,9 +1841,9 @@ static void output_syscall_dispatcher(void)
|
||||||
output( "\tldp q26, q27, [sp, #0x2c0]\n" );
|
output( "\tldp q26, q27, [sp, #0x2c0]\n" );
|
||||||
output( "\tldp q28, q29, [sp, #0x2e0]\n" );
|
output( "\tldp q28, q29, [sp, #0x2e0]\n" );
|
||||||
output( "\tldp q30, q31, [sp, #0x300]\n" );
|
output( "\tldp q30, q31, [sp, #0x300]\n" );
|
||||||
output( "\tldr w9, [x10, #0x118]\n" );
|
output( "\tldr w9, [sp, #0x118]\n" );
|
||||||
output( "\tmsr FPCR, x9\n" );
|
output( "\tmsr FPCR, x9\n" );
|
||||||
output( "\tldr w9, [x10, #0x11c]\n" );
|
output( "\tldr w9, [sp, #0x11c]\n" );
|
||||||
output( "\tmsr FPSR, x9\n" );
|
output( "\tmsr FPSR, x9\n" );
|
||||||
output( "1:\ttbz x16, #1, 1f\n" ); /* CONTEXT_INTEGER */
|
output( "1:\ttbz x16, #1, 1f\n" ); /* CONTEXT_INTEGER */
|
||||||
output( "\tldp x0, x1, [sp, #0x00]\n" );
|
output( "\tldp x0, x1, [sp, #0x00]\n" );
|
||||||
|
@ -1857,6 +1862,10 @@ static void output_syscall_dispatcher(void)
|
||||||
output( "4:\tmov x0, #0x%x\n", invalid_param & 0xffff0000 );
|
output( "4:\tmov x0, #0x%x\n", invalid_param & 0xffff0000 );
|
||||||
output( "\tmovk x0, #0x%x\n", invalid_param & 0x0000ffff );
|
output( "\tmovk x0, #0x%x\n", invalid_param & 0x0000ffff );
|
||||||
output( "\tb 3b\n" );
|
output( "\tb 3b\n" );
|
||||||
|
output( "%s\n", asm_globl("__wine_syscall_dispatcher_return") );
|
||||||
|
output( "\tmov sp, x0\n" );
|
||||||
|
output( "\tmov x0, x1\n" );
|
||||||
|
output( "\tb 3b\n" );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
|
Loading…
Reference in New Issue