mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-01 22:04:04 +00:00
ntdll: Move the syscall dispatcher implementation to the platform-specific files.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
847db3c1d3
commit
ff04d8a4c2
|
@ -1031,4 +1031,77 @@ __ASM_GLOBAL_FUNC( signal_exit_thread,
|
|||
"movne sp, r3\n\t"
|
||||
"blx r1" )
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* __wine_syscall_dispatcher
|
||||
*/
|
||||
__ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
|
||||
"mrc p15, 0, r1, c13, c0, 2\n\t" /* NtCurrentTeb() */
|
||||
"ldr r1, [r1, #0x1d8]\n\t" /* arm_thread_data()->syscall_frame */
|
||||
"add r0, r1, #0x10\n\t"
|
||||
"stm r0, {r4-r12,lr}\n\t"
|
||||
"str sp, [r1, #0x38]\n\t"
|
||||
"str r3, [r1, #0x3c]\n\t"
|
||||
"mrs r0, CPSR\n\t"
|
||||
"bfi r0, lr, #5, #1\n\t" /* set thumb bit */
|
||||
"str r0, [r1, #0x40]\n\t"
|
||||
"mov r0, #0\n\t"
|
||||
"str r0, [r1, #0x44]\n\t" /* frame->restore_flags */
|
||||
#ifndef __SOFTFP__
|
||||
"vmrs r0, fpscr\n\t"
|
||||
"str r0, [r1, #0x48]\n\t"
|
||||
"add r0, r1, #0x60\n\t"
|
||||
"vstm r0, {d0-d15}\n\t"
|
||||
#endif
|
||||
"mov r6, sp\n\t"
|
||||
"mov sp, r1\n\t"
|
||||
"mov r8, r1\n\t"
|
||||
"ldr r5, [r1, #0x50]\n\t" /* frame->syscall_table */
|
||||
"ubfx r4, ip, #12, #2\n\t" /* syscall table number */
|
||||
"bfc ip, #12, #20\n\t" /* syscall number */
|
||||
"add r4, r5, r4, lsl #4\n\t"
|
||||
"ldr r5, [r4, #8]\n\t" /* table->ServiceLimit */
|
||||
"cmp ip, r5\n\t"
|
||||
"bcs 5f\n\t"
|
||||
"ldr r5, [r4, #12]\n\t" /* table->ArgumentTable */
|
||||
"ldrb r5, [r5, ip]\n\t"
|
||||
"cmp r5, #16\n\t"
|
||||
"it le\n\t"
|
||||
"movle r5, #16\n\t"
|
||||
"sub r0, sp, r5\n\t"
|
||||
"and r0, #~7\n\t"
|
||||
"mov sp, r0\n"
|
||||
"2:\tsubs r5, r5, #4\n\t"
|
||||
"ldr r0, [r6, r5]\n\t"
|
||||
"str r0, [sp, r5]\n\t"
|
||||
"bgt 2b\n\t"
|
||||
"pop {r0-r3}\n\t" /* first 4 args are in registers */
|
||||
"ldr r5, [r4]\n\t" /* table->ServiceTable */
|
||||
"ldr ip, [r5, ip, lsl #2]\n\t"
|
||||
"blx ip\n"
|
||||
"4:\tldr ip, [r8, #0x44]\n\t" /* frame->restore_flags */
|
||||
#ifndef __SOFTFP__
|
||||
"tst ip, #4\n\t" /* CONTEXT_FLOATING_POINT */
|
||||
"beq 3f\n\t"
|
||||
"ldr r4, [r8, #0x48]\n\t"
|
||||
"vmsr fpscr, r4\n\t"
|
||||
"add r4, r8, #0x60\n\t"
|
||||
"vldm r4, {d0-d15}\n"
|
||||
"3:\n\t"
|
||||
#endif
|
||||
"tst ip, #2\n\t" /* CONTEXT_INTEGER */
|
||||
"it ne\n\t"
|
||||
"ldmne r8, {r0-r3}\n\t"
|
||||
"ldr lr, [r8, #0x3c]\n\t"
|
||||
"ldr sp, [r8, #0x38]\n\t"
|
||||
"add r8, r8, #0x10\n\t"
|
||||
"ldm r8, {r4-r12,pc}\n"
|
||||
"5:\tmovw r0, #0x000d\n\t" /* STATUS_INVALID_PARAMETER */
|
||||
"movt r0, #0xc000\n\t"
|
||||
"b 4b\n"
|
||||
__ASM_NAME("__wine_syscall_dispatcher_return") ":\n\t"
|
||||
"mov r8, r0\n\t"
|
||||
"mov r0, r1\n\t"
|
||||
"b 4b" )
|
||||
|
||||
#endif /* __arm__ */
|
||||
|
|
|
@ -1224,6 +1224,133 @@ __ASM_GLOBAL_FUNC( signal_exit_thread,
|
|||
"1:\tldp x29, x30, [sp], #16\n\t"
|
||||
"br x1" )
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* __wine_syscall_dispatcher
|
||||
*/
|
||||
__ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
|
||||
/* FIXME: use x18 directly instead */
|
||||
"stp x0, x1, [sp, #-96]!\n\t"
|
||||
"stp x2, x3, [sp, #16]\n\t"
|
||||
"stp x4, x5, [sp, #32]\n\t"
|
||||
"stp x6, x7, [sp, #48]\n\t"
|
||||
"stp x8, x9, [sp, #64]\n\t"
|
||||
"str x30, [sp, #80]\n\t"
|
||||
"bl " __ASM_NAME("NtCurrentTeb") "\n\t"
|
||||
"mov x18, x0\n\t"
|
||||
"ldp x2, x3, [sp, #16]\n\t"
|
||||
"ldp x4, x5, [sp, #32]\n\t"
|
||||
"ldp x6, x7, [sp, #48]\n\t"
|
||||
"ldp x8, x9, [sp, #64]\n\t"
|
||||
"ldr x30, [sp, #80]\n\t"
|
||||
"ldp x0, x1, [sp], #96\n\t"
|
||||
|
||||
"ldr x10, [x18, #0x2f8]\n\t" /* arm64_thread_data()->syscall_frame */
|
||||
"stp x18, x19, [x10, #0x90]\n\t"
|
||||
"stp x20, x21, [x10, #0xa0]\n\t"
|
||||
"stp x22, x23, [x10, #0xb0]\n\t"
|
||||
"stp x24, x25, [x10, #0xc0]\n\t"
|
||||
"stp x26, x27, [x10, #0xd0]\n\t"
|
||||
"stp x28, x29, [x10, #0xe0]\n\t"
|
||||
"mov x19, sp\n\t"
|
||||
"stp x9, x19, [x10, #0xf0]\n\t"
|
||||
"mrs x9, NZCV\n\t"
|
||||
"stp x30, x9, [x10, #0x100]\n\t"
|
||||
"mrs x9, FPCR\n\t"
|
||||
"str w9, [x10, #0x128]\n\t"
|
||||
"mrs x9, FPSR\n\t"
|
||||
"str w9, [x10, #0x12c]\n\t"
|
||||
"stp q0, q1, [x10, #0x130]\n\t"
|
||||
"stp q2, q3, [x10, #0x150]\n\t"
|
||||
"stp q4, q5, [x10, #0x170]\n\t"
|
||||
"stp q6, q7, [x10, #0x190]\n\t"
|
||||
"stp q8, q9, [x10, #0x1b0]\n\t"
|
||||
"stp q10, q11, [x10, #0x1d0]\n\t"
|
||||
"stp q12, q13, [x10, #0x1f0]\n\t"
|
||||
"stp q14, q15, [x10, #0x210]\n\t"
|
||||
"stp q16, q17, [x10, #0x230]\n\t"
|
||||
"stp q18, q19, [x10, #0x250]\n\t"
|
||||
"stp q20, q21, [x10, #0x270]\n\t"
|
||||
"stp q22, q23, [x10, #0x290]\n\t"
|
||||
"stp q24, q25, [x10, #0x2b0]\n\t"
|
||||
"stp q26, q27, [x10, #0x2d0]\n\t"
|
||||
"stp q28, q29, [x10, #0x2f0]\n\t"
|
||||
"stp q30, q31, [x10, #0x310]\n\t"
|
||||
"mov sp, x10\n\t"
|
||||
"and x20, x8, #0xfff\n\t" /* syscall number */
|
||||
"ubfx x21, x8, #12, #2\n\t" /* syscall table number */
|
||||
"ldr x16, [x10, #0x118]\n\t" /* frame->syscall_table */
|
||||
"add x21, x16, x21, lsl #5\n\t"
|
||||
"ldr x16, [x21, #16]\n\t" /* table->ServiceLimit */
|
||||
"cmp x20, x16\n\t"
|
||||
"bcs 4f\n\t"
|
||||
"mov x22, sp\n\t"
|
||||
"ldr x16, [x21, #24]\n\t" /* table->ArgumentTable */
|
||||
"ldrb w9, [x16, x20]\n\t"
|
||||
"subs x9, x9, #64\n\t"
|
||||
"bls 2f\n\t"
|
||||
"sub sp, sp, x9\n\t"
|
||||
"tbz x9, #3, 1f\n\t"
|
||||
"sub sp, sp, #8\n"
|
||||
"1:\tsub x9, x9, #8\n\t"
|
||||
"ldr x10, [x19, x9]\n\t"
|
||||
"str x10, [sp, x9]\n\t"
|
||||
"cbnz x9, 1b\n"
|
||||
"2:\tldr x16, [x21]\n\t" /* table->ServiceTable */
|
||||
"ldr x16, [x16, x20, lsl 3]\n\t"
|
||||
"blr x16\n\t"
|
||||
"mov sp, x22\n"
|
||||
"3:\tldp x18, x19, [sp, #0x90]\n\t"
|
||||
"ldp x20, x21, [sp, #0xa0]\n\t"
|
||||
"ldp x22, x23, [sp, #0xb0]\n\t"
|
||||
"ldp x24, x25, [sp, #0xc0]\n\t"
|
||||
"ldp x26, x27, [sp, #0xd0]\n\t"
|
||||
"ldp x28, x29, [sp, #0xe0]\n\t"
|
||||
"ldr w16, [sp, #0x10c]\n\t" /* frame->restore_flags */
|
||||
"tbz x16, #2, 1f\n\t" /* CONTEXT_FLOATING_POINT */
|
||||
"ldp q0, q1, [sp, #0x130]\n\t"
|
||||
"ldp q2, q3, [sp, #0x150]\n\t"
|
||||
"ldp q4, q5, [sp, #0x170]\n\t"
|
||||
"ldp q6, q7, [sp, #0x190]\n\t"
|
||||
"ldp q8, q9, [sp, #0x1b0]\n\t"
|
||||
"ldp q10, q11, [sp, #0x1d0]\n\t"
|
||||
"ldp q12, q13, [sp, #0x1f0]\n\t"
|
||||
"ldp q14, q15, [sp, #0x210]\n\t"
|
||||
"ldp q16, q17, [sp, #0x230]\n\t"
|
||||
"ldp q18, q19, [sp, #0x250]\n\t"
|
||||
"ldp q20, q21, [sp, #0x270]\n\t"
|
||||
"ldp q22, q23, [sp, #0x290]\n\t"
|
||||
"ldp q24, q25, [sp, #0x2b0]\n\t"
|
||||
"ldp q26, q27, [sp, #0x2d0]\n\t"
|
||||
"ldp q28, q29, [sp, #0x2f0]\n\t"
|
||||
"ldp q30, q31, [sp, #0x310]\n\t"
|
||||
"ldr w9, [sp, #0x128]\n\t"
|
||||
"msr FPCR, x9\n\t"
|
||||
"ldr w9, [sp, #0x12c]\n\t"
|
||||
"msr FPSR, x9\n"
|
||||
"1:\ttbz x16, #1, 1f\n\t" /* CONTEXT_INTEGER */
|
||||
"ldp x0, x1, [sp, #0x00]\n\t"
|
||||
"ldp x2, x3, [sp, #0x10]\n\t"
|
||||
"ldp x4, x5, [sp, #0x20]\n\t"
|
||||
"ldp x6, x7, [sp, #0x30]\n\t"
|
||||
"ldp x8, x9, [sp, #0x40]\n\t"
|
||||
"ldp x10, x11, [sp, #0x50]\n\t"
|
||||
"ldp x12, x13, [sp, #0x60]\n\t"
|
||||
"ldp x14, x15, [sp, #0x70]\n"
|
||||
"1:\tldp x16, x17, [sp, #0x100]\n\t"
|
||||
"msr NZCV, x17\n\t"
|
||||
"ldp x30, x17, [sp, #0xf0]\n\t"
|
||||
"mov sp, x17\n\t"
|
||||
"ret x16\n"
|
||||
"4:\tmov x0, #0xc0000000\n\t" /* STATUS_INVALID_PARAMETER */
|
||||
"movk x0, #0x000d\n\t"
|
||||
"b 3b\n"
|
||||
__ASM_NAME("__wine_syscall_dispatcher_return") ":\n\t"
|
||||
"mov sp, x0\n\t"
|
||||
"mov x0, x1\n\t"
|
||||
"b 3b" )
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NtCurrentTeb (NTDLL.@)
|
||||
*/
|
||||
|
|
|
@ -1770,7 +1770,7 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, void *stack_ptr,
|
|||
*/
|
||||
static BOOL handle_syscall_trap( ucontext_t *sigcontext )
|
||||
{
|
||||
extern void __wine_syscall_dispatcher_prolog_end(void);
|
||||
extern void __wine_syscall_dispatcher_prolog_end(void) DECLSPEC_HIDDEN;
|
||||
struct syscall_frame *frame = x86_thread_data()->syscall_frame;
|
||||
|
||||
/* disallow single-stepping through a syscall */
|
||||
|
@ -2487,6 +2487,135 @@ __ASM_GLOBAL_FUNC( signal_exit_thread,
|
|||
"pushl %eax\n\t"
|
||||
"call *%ecx" )
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* __wine_syscall_dispatcher
|
||||
*/
|
||||
__ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
|
||||
"movl %fs:0x1f8,%ecx\n\t" /* x86_thread_data()->syscall_frame */
|
||||
"movw $0,0x02(%ecx)\n\t" /* frame->restore_flags */
|
||||
"popl 0x08(%ecx)\n\t" /* frame->eip */
|
||||
"pushfl\n\t"
|
||||
"popl 0x04(%ecx)\n" /* frame->eflags */
|
||||
__ASM_NAME("__wine_syscall_dispatcher_prolog_end") ":\n\t"
|
||||
"movl %esp,0x0c(%ecx)\n\t" /* frame->esp */
|
||||
"movw %cs,0x10(%ecx)\n\t"
|
||||
"movw %ss,0x12(%ecx)\n\t"
|
||||
"movw %ds,0x14(%ecx)\n\t"
|
||||
"movw %es,0x16(%ecx)\n\t"
|
||||
"movw %fs,0x18(%ecx)\n\t"
|
||||
"movw %gs,0x1a(%ecx)\n\t"
|
||||
"movl %eax,0x1c(%ecx)\n\t"
|
||||
"movl %ebx,0x20(%ecx)\n\t"
|
||||
"movl %edi,0x2c(%ecx)\n\t"
|
||||
"movl %esi,0x30(%ecx)\n\t"
|
||||
"movl %ebp,0x34(%ecx)\n\t"
|
||||
"leal 0x34(%ecx),%ebp\n\t"
|
||||
"leal 4(%esp),%esi\n\t" /* first argument */
|
||||
"movl %eax,%ebx\n\t"
|
||||
"shrl $8,%ebx\n\t"
|
||||
"andl $0x30,%ebx\n\t" /* syscall table number */
|
||||
"addl 0x38(%ecx),%ebx\n\t" /* frame->syscall_table */
|
||||
"testl $3,(%ecx)\n\t" /* frame->syscall_flags & (SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC) */
|
||||
"jz 2f\n\t"
|
||||
"movl $7,%eax\n\t"
|
||||
"xorl %edx,%edx\n\t"
|
||||
"movl %edx,0x240(%ecx)\n\t"
|
||||
"movl %edx,0x244(%ecx)\n\t"
|
||||
"movl %edx,0x248(%ecx)\n\t"
|
||||
"movl %edx,0x24c(%ecx)\n\t"
|
||||
"movl %edx,0x250(%ecx)\n\t"
|
||||
"movl %edx,0x254(%ecx)\n\t"
|
||||
"testl $2,(%ecx)\n\t" /* frame->syscall_flags & SYSCALL_HAVE_XSAVEC */
|
||||
"jz 1f\n\t"
|
||||
"movl %edx,0x258(%ecx)\n\t"
|
||||
"movl %edx,0x25c(%ecx)\n\t"
|
||||
"movl %edx,0x260(%ecx)\n\t"
|
||||
"movl %edx,0x264(%ecx)\n\t"
|
||||
"movl %edx,0x268(%ecx)\n\t"
|
||||
"movl %edx,0x26c(%ecx)\n\t"
|
||||
"movl %edx,0x270(%ecx)\n\t"
|
||||
"movl %edx,0x274(%ecx)\n\t"
|
||||
"movl %edx,0x278(%ecx)\n\t"
|
||||
"movl %edx,0x27c(%ecx)\n\t"
|
||||
"xsavec 0x40(%ecx)\n\t"
|
||||
"jmp 4f\n"
|
||||
"1:\txsave 0x40(%ecx)\n\t"
|
||||
"jmp 4f\n"
|
||||
"2:\ttestl $4,(%ecx)\n\t" /* frame->syscall_flags & SYSCALL_HAVE_FXSAVE */
|
||||
"jz 3f\n\t"
|
||||
"fxsave 0x40(%ecx)\n\t"
|
||||
"jmp 4f\n"
|
||||
"3:\tfnsave 0x40(%ecx)\n\t"
|
||||
"fwait\n"
|
||||
"4:\tmovl %ecx,%esp\n\t"
|
||||
"movl 0x1c(%esp),%edx\n\t" /* frame->eax */
|
||||
"andl $0xfff,%edx\n\t" /* syscall number */
|
||||
"cmpl 8(%ebx),%edx\n\t" /* table->ServiceLimit */
|
||||
"jae 6f\n\t"
|
||||
"movl 12(%ebx),%eax\n\t" /* table->ArgumentTable */
|
||||
"movzbl (%eax,%edx,1),%ecx\n\t"
|
||||
"movl (%ebx),%eax\n\t" /* table->ServiceTable */
|
||||
"subl %ecx,%esp\n\t"
|
||||
"shrl $2,%ecx\n\t"
|
||||
"andl $~15,%esp\n\t"
|
||||
"movl %esp,%edi\n\t"
|
||||
"cld\n\t"
|
||||
"rep; movsl\n\t"
|
||||
"call *(%eax,%edx,4)\n\t"
|
||||
"leal -0x34(%ebp),%esp\n"
|
||||
"5:\tmovl 0(%esp),%ecx\n\t" /* frame->syscall_flags + (frame->restore_flags << 16) */
|
||||
"testl $0x68 << 16,%ecx\n\t" /* CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS | CONTEXT_XSAVE */
|
||||
"jz 3f\n\t"
|
||||
"testl $3,%ecx\n\t" /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||
"jz 1f\n\t"
|
||||
"movl %eax,%esi\n\t"
|
||||
"movl $7,%eax\n\t"
|
||||
"xorl %edx,%edx\n\t"
|
||||
"xrstor 0x40(%esp)\n\t"
|
||||
"movl %esi,%eax\n\t"
|
||||
"jmp 3f\n"
|
||||
"1:\ttestl $4,%ecx\n\t" /* SYSCALL_HAVE_FXSAVE */
|
||||
"jz 2f\n\t"
|
||||
"fxrstor 0x40(%esp)\n\t"
|
||||
"jmp 3f\n"
|
||||
"2:\tfrstor 0x40(%esp)\n\t"
|
||||
"fwait\n"
|
||||
"3:\tmovl 0x2c(%esp),%edi\n\t"
|
||||
"movl 0x30(%esp),%esi\n\t"
|
||||
"movl 0x34(%esp),%ebp\n\t"
|
||||
"testl $0x7 << 16,%ecx\n\t" /* CONTEXT_CONTROL | CONTEXT_SEGMENTS | CONTEXT_INTEGER */
|
||||
"jnz 1f\n\t"
|
||||
"movl 0x20(%esp),%ebx\n\t"
|
||||
"movl 0x08(%esp),%ecx\n\t" /* frame->eip */
|
||||
"movl 0x0c(%esp),%esp\n\t" /* frame->esp */
|
||||
"jmpl *%ecx\n"
|
||||
"1:\ttestl $0x2 << 16,%ecx\n\t" /* CONTEXT_INTEGER */
|
||||
"jz 1f\n\t"
|
||||
"movl 0x1c(%esp),%eax\n\t"
|
||||
"movl 0x24(%esp),%ecx\n\t"
|
||||
"movl 0x28(%esp),%edx\n"
|
||||
"1:\tmovl 0x0c(%esp),%ebx\n\t" /* frame->esp */
|
||||
"movw 0x12(%esp),%ss\n\t"
|
||||
"xchgl %ebx,%esp\n\t"
|
||||
"pushl 0x04(%ebx)\n\t" /* frame->eflags */
|
||||
"pushl 0x10(%ebx)\n\t" /* frame->cs */
|
||||
"pushl 0x08(%ebx)\n\t" /* frame->eip */
|
||||
"pushl 0x14(%ebx)\n\t" /* frame->ds */
|
||||
"movw 0x16(%ebx),%es\n\t"
|
||||
"movw 0x18(%ebx),%fs\n\t"
|
||||
"movw 0x1a(%ebx),%gs\n\t"
|
||||
"movl 0x20(%ebx),%ebx\n\t"
|
||||
"popl %ds\n\t"
|
||||
"iret\n"
|
||||
"6:\tmovl $0xc000000d,%eax\n\t" /* STATUS_INVALID_PARAMETER */
|
||||
"jmp 5b\n"
|
||||
__ASM_NAME("__wine_syscall_dispatcher_return") ":\n\t"
|
||||
"movl 8(%esp),%eax\n\t"
|
||||
"movl 4(%esp),%esp\n\t"
|
||||
"jmp 5b" )
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NtCurrentTeb (NTDLL.@)
|
||||
*/
|
||||
|
|
|
@ -3106,4 +3106,146 @@ __ASM_GLOBAL_FUNC( signal_exit_thread,
|
|||
__ASM_CFI(".cfi_rel_offset %r15,8\n\t")
|
||||
"call *%rsi" )
|
||||
|
||||
/***********************************************************************
|
||||
* __wine_syscall_dispatcher
|
||||
*/
|
||||
__ASM_GLOBAL_FUNC( __wine_syscall_dispatcher,
|
||||
"movq %gs:0x30,%rcx\n\t"
|
||||
"movq 0x328(%rcx),%rcx\n\t" /* amd64_thread_data()->syscall_frame */
|
||||
"popq 0x70(%rcx)\n\t" /* frame->rip */
|
||||
"pushfq\n\t"
|
||||
"popq 0x80(%rcx)\n\t"
|
||||
"movl $0,0x94(%rcx)\n\t" /* frame->restore_flags */
|
||||
__ASM_NAME("__wine_syscall_dispatcher_prolog_end") ":\n\t"
|
||||
"movq %rax,0x00(%rcx)\n\t"
|
||||
"movq %rbx,0x08(%rcx)\n\t"
|
||||
"movq %rdx,0x18(%rcx)\n\t"
|
||||
"movq %rsi,0x20(%rcx)\n\t"
|
||||
"movq %rdi,0x28(%rcx)\n\t"
|
||||
"movq %r12,0x50(%rcx)\n\t"
|
||||
"movq %r13,0x58(%rcx)\n\t"
|
||||
"movq %r14,0x60(%rcx)\n\t"
|
||||
"movq %r15,0x68(%rcx)\n\t"
|
||||
"movw %cs,0x78(%rcx)\n\t"
|
||||
"movw %ds,0x7a(%rcx)\n\t"
|
||||
"movw %es,0x7c(%rcx)\n\t"
|
||||
"movw %fs,0x7e(%rcx)\n\t"
|
||||
"movq %rsp,0x88(%rcx)\n\t"
|
||||
"movw %ss,0x90(%rcx)\n\t"
|
||||
"movw %gs,0x92(%rcx)\n\t"
|
||||
"movq %rbp,0x98(%rcx)\n\t"
|
||||
/* Legends of Runeterra hooks the first system call return instruction, and
|
||||
* depends on us returning to it. Adjust the return address accordingly. */
|
||||
"subq $0xb,0x70(%rcx)\n\t"
|
||||
"movl 0xb0(%rcx),%r14d\n\t" /* frame->syscall_flags */
|
||||
"testl $3,%r14d\n\t" /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||
"jz 2f\n\t"
|
||||
"movl $7,%eax\n\t"
|
||||
"xorl %edx,%edx\n\t"
|
||||
"movq %rdx,0x2c0(%rcx)\n\t"
|
||||
"movq %rdx,0x2c8(%rcx)\n\t"
|
||||
"movq %rdx,0x2d0(%rcx)\n\t"
|
||||
"testl $2,%r14d\n\t" /* SYSCALL_HAVE_XSAVEC */
|
||||
"jz 1f\n\t"
|
||||
"movq %rdx,0x2d8(%rcx)\n\t"
|
||||
"movq %rdx,0x2e0(%rcx)\n\t"
|
||||
"movq %rdx,0x2e8(%rcx)\n\t"
|
||||
"movq %rdx,0x2f0(%rcx)\n\t"
|
||||
"movq %rdx,0x2f8(%rcx)\n\t"
|
||||
"xsavec64 0xc0(%rcx)\n\t"
|
||||
"jmp 3f\n"
|
||||
"1:\txsave64 0xc0(%rcx)\n\t"
|
||||
"jmp 3f\n"
|
||||
"2:\tfxsave64 0xc0(%rcx)\n"
|
||||
"3:\tleaq 0x98(%rcx),%rbp\n\t"
|
||||
#ifdef __linux__
|
||||
"testl $12,%r14d\n\t" /* SYSCALL_HAVE_PTHREAD_TEB | SYSCALL_HAVE_WRFSGSBASE */
|
||||
"jz 2f\n\t"
|
||||
"movq %gs:0x330,%rsi\n\t" /* amd64_thread_data()->pthread_teb */
|
||||
"testl $8,%r14d\n\t" /* SYSCALL_HAVE_WRFSGSBASE */
|
||||
"jz 1f\n\t"
|
||||
"wrfsbase %rsi\n\t"
|
||||
"jmp 2f\n"
|
||||
"1:\tmov $0x1002,%edi\n\t" /* ARCH_SET_FS */
|
||||
"mov $158,%eax\n\t" /* SYS_arch_prctl */
|
||||
"syscall\n\t"
|
||||
"leaq -0x98(%rbp),%rcx\n"
|
||||
"2:\n\t"
|
||||
#endif
|
||||
"leaq 0x28(%rsp),%rsi\n\t" /* first argument */
|
||||
"movq %rcx,%rsp\n\t"
|
||||
"movq 0x00(%rcx),%rax\n\t"
|
||||
"movq 0x18(%rcx),%rdx\n\t"
|
||||
"movl %eax,%ebx\n\t"
|
||||
"shrl $8,%ebx\n\t"
|
||||
"andl $0x30,%ebx\n\t" /* syscall table number */
|
||||
"movq 0xa8(%rcx),%rcx\n\t" /* frame->syscall_table */
|
||||
"leaq (%rcx,%rbx,2),%rbx\n\t"
|
||||
"andl $0xfff,%eax\n\t" /* syscall number */
|
||||
"cmpq 16(%rbx),%rax\n\t" /* table->ServiceLimit */
|
||||
"jae 5f\n\t"
|
||||
"movq 24(%rbx),%rcx\n\t" /* table->ArgumentTable */
|
||||
"movzbl (%rcx,%rax),%ecx\n\t"
|
||||
"subq $0x20,%rcx\n\t"
|
||||
"jbe 1f\n\t"
|
||||
"subq %rcx,%rsp\n\t"
|
||||
"shrq $3,%rcx\n\t"
|
||||
"andq $~15,%rsp\n\t"
|
||||
"movq %rsp,%rdi\n\t"
|
||||
"cld\n\t"
|
||||
"rep; movsq\n"
|
||||
"1:\tmovq %r10,%rcx\n\t"
|
||||
"subq $0x20,%rsp\n\t"
|
||||
"movq (%rbx),%r10\n\t" /* table->ServiceTable */
|
||||
"callq *(%r10,%rax,8)\n\t"
|
||||
"leaq -0x98(%rbp),%rcx\n"
|
||||
"2:\tmovl 0x94(%rcx),%edx\n\t" /* frame->restore_flags */
|
||||
#ifdef __linux__
|
||||
"testl $12,%r14d\n\t" /* SYSCALL_HAVE_PTHREAD_TEB | SYSCALL_HAVE_WRFSGSBASE */
|
||||
"jz 1f\n\t"
|
||||
"movw 0x7e(%rcx),%fs\n"
|
||||
"1:\n\t"
|
||||
#endif
|
||||
"testl $0x48,%edx\n\t" /* CONTEXT_FLOATING_POINT | CONTEXT_XSTATE */
|
||||
"jz 4f\n\t"
|
||||
"testl $3,%r14d\n\t" /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||
"jz 3f\n\t"
|
||||
"movq %rax,%r11\n\t"
|
||||
"movl $7,%eax\n\t"
|
||||
"xorl %edx,%edx\n\t"
|
||||
"xrstor64 0xc0(%rcx)\n\t"
|
||||
"movq %r11,%rax\n\t"
|
||||
"movl 0x94(%rcx),%edx\n\t"
|
||||
"jmp 4f\n"
|
||||
"3:\tfxrstor64 0xc0(%rcx)\n"
|
||||
"4:\tmovq 0x98(%rcx),%rbp\n\t"
|
||||
"movq 0x68(%rcx),%r15\n\t"
|
||||
"movq 0x60(%rcx),%r14\n\t"
|
||||
"movq 0x58(%rcx),%r13\n\t"
|
||||
"movq 0x50(%rcx),%r12\n\t"
|
||||
"movq 0x28(%rcx),%rdi\n\t"
|
||||
"movq 0x20(%rcx),%rsi\n\t"
|
||||
"movq 0x08(%rcx),%rbx\n\t"
|
||||
"testl $0x3,%edx\n\t" /* CONTEXT_CONTROL | CONTEXT_INTEGER */
|
||||
"jnz 1f\n\t"
|
||||
"movq 0x88(%rcx),%rsp\n\t"
|
||||
"jmpq *0x70(%rcx)\n" /* frame->rip */
|
||||
"1:\tleaq 0x70(%rcx),%rsp\n\t"
|
||||
"testl $0x2,%edx\n\t" /* CONTEXT_INTEGER */
|
||||
"jz 1f\n\t"
|
||||
"movq 0x00(%rcx),%rax\n\t"
|
||||
"movq 0x18(%rcx),%rdx\n\t"
|
||||
"movq 0x30(%rcx),%r8\n\t"
|
||||
"movq 0x38(%rcx),%r9\n\t"
|
||||
"movq 0x40(%rcx),%r10\n\t"
|
||||
"movq 0x48(%rcx),%r11\n\t"
|
||||
"movq 0x10(%rcx),%rcx\n"
|
||||
"1:\tiretq\n"
|
||||
"5:\tmovl $0xc000000d,%edx\n\t" /* STATUS_INVALID_PARAMETER */
|
||||
"movq %rsp,%rcx\n"
|
||||
__ASM_NAME("__wine_syscall_dispatcher_return") ":\n\t"
|
||||
"movl 0xb0(%rcx),%r14d\n\t" /* frame->syscall_flags */
|
||||
"movq %rdx,%rax\n\t"
|
||||
"jmp 2b" )
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
|
|
@ -1420,470 +1420,6 @@ static int cmp_link_name( const void *e1, const void *e2 )
|
|||
}
|
||||
|
||||
|
||||
/* output dispatcher for system calls */
|
||||
static void output_syscall_dispatcher(void)
|
||||
{
|
||||
const unsigned int invalid_param = 0xc000000d; /* STATUS_INVALID_PARAMETER */
|
||||
unsigned int i;
|
||||
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( "\t%s\n", func_declaration("__wine_syscall_dispatcher") );
|
||||
output( "%s\n", asm_globl("__wine_syscall_dispatcher") );
|
||||
output_cfi( ".cfi_startproc" );
|
||||
switch (target_cpu)
|
||||
{
|
||||
case CPU_x86:
|
||||
output( "\tmovl %%fs:0x1f8,%%ecx\n" ); /* x86_thread_data()->syscall_frame */
|
||||
output( "\tmovw $0,0x02(%%ecx)\n" ); /* frame->restore_flags */
|
||||
output( "\tpopl 0x08(%%ecx)\n" ); /* frame->eip */
|
||||
output( "\tpushfl\n" );
|
||||
output( "\tpopl 0x04(%%ecx)\n" ); /* frame->eflags */
|
||||
output( "%s\n", asm_globl("__wine_syscall_dispatcher_prolog_end") );
|
||||
output( "\tmovl %%esp,0x0c(%%ecx)\n" ); /* frame->esp */
|
||||
output( "\tmovw %%cs,0x10(%%ecx)\n" );
|
||||
output( "\tmovw %%ss,0x12(%%ecx)\n" );
|
||||
output( "\tmovw %%ds,0x14(%%ecx)\n" );
|
||||
output( "\tmovw %%es,0x16(%%ecx)\n" );
|
||||
output( "\tmovw %%fs,0x18(%%ecx)\n" );
|
||||
output( "\tmovw %%gs,0x1a(%%ecx)\n" );
|
||||
output( "\tmovl %%eax,0x1c(%%ecx)\n" );
|
||||
output( "\tmovl %%ebx,0x20(%%ecx)\n" );
|
||||
output( "\tmovl %%edi,0x2c(%%ecx)\n" );
|
||||
output( "\tmovl %%esi,0x30(%%ecx)\n" );
|
||||
output( "\tmovl %%ebp,0x34(%%ecx)\n" );
|
||||
output( "\tleal 0x34(%%ecx),%%ebp\n" );
|
||||
output( "\tleal 4(%%esp),%%esi\n" ); /* first argument */
|
||||
output( "\tmovl %%eax,%%ebx\n" );
|
||||
output( "\tshrl $8,%%ebx\n" );
|
||||
output( "\tandl $0x30,%%ebx\n" ); /* syscall table number */
|
||||
output( "\taddl 0x38(%%ecx),%%ebx\n" ); /* frame->syscall_table */
|
||||
output( "\ttestl $3,(%%ecx)\n" ); /* frame->syscall_flags & (SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC) */
|
||||
output( "\tjz 2f\n" );
|
||||
output( "\tmovl $7,%%eax\n" );
|
||||
output( "\txorl %%edx,%%edx\n" );
|
||||
for (i = 0; i < 6; i++) output( "\tmovl %%edx,0x%x(%%ecx)\n", 0x240 + i * 4 );
|
||||
output( "\ttestl $2,(%%ecx)\n" ); /* frame->syscall_flags & SYSCALL_HAVE_XSAVEC */
|
||||
output( "\tjz 1f\n" );
|
||||
for (i = 6; i < 16; i++) output( "\tmovl %%edx,0x%x(%%ecx)\n", 0x240 + i * 4 );
|
||||
output( "\txsavec 0x40(%%ecx)\n" );
|
||||
output( "\tjmp 4f\n" );
|
||||
output( "1:\txsave 0x40(%%ecx)\n" );
|
||||
output( "\tjmp 4f\n" );
|
||||
output( "2:\ttestl $4,(%%ecx)\n" ); /* frame->syscall_flags & SYSCALL_HAVE_FXSAVE */
|
||||
output( "\tjz 3f\n" );
|
||||
output( "\tfxsave 0x40(%%ecx)\n" );
|
||||
output( "\tjmp 4f\n" );
|
||||
output( "3:\tfnsave 0x40(%%ecx)\n" );
|
||||
output( "\tfwait\n" );
|
||||
output( "4:\tmovl %%ecx,%%esp\n" );
|
||||
output( "\tmovl 0x1c(%%esp),%%edx\n" ); /* frame->eax */
|
||||
output( "\tandl $0xfff,%%edx\n" ); /* syscall number */
|
||||
output( "\tcmpl 8(%%ebx),%%edx\n" ); /* table->ServiceLimit */
|
||||
output( "\tjae 6f\n" );
|
||||
output( "\tmovl 12(%%ebx),%%eax\n" ); /* table->ArgumentTable */
|
||||
output( "\tmovzbl (%%eax,%%edx,1),%%ecx\n" );
|
||||
output( "\tmovl (%%ebx),%%eax\n" ); /* table->ServiceTable */
|
||||
output( "\tsubl %%ecx,%%esp\n" );
|
||||
output( "\tshrl $2,%%ecx\n" );
|
||||
output( "\tandl $~15,%%esp\n" );
|
||||
output( "\tmovl %%esp,%%edi\n" );
|
||||
output( "\tcld\n" );
|
||||
output( "\trep; movsl\n" );
|
||||
output( "\tcall *(%%eax,%%edx,4)\n" );
|
||||
output( "\tleal -0x34(%%ebp),%%esp\n" );
|
||||
output( "5:\tmovl 0(%%esp),%%ecx\n" ); /* frame->syscall_flags + (frame->restore_flags << 16) */
|
||||
output( "\ttestl $0x68 << 16,%%ecx\n" ); /* CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS | CONTEXT_XSAVE */
|
||||
output( "\tjz 3f\n" );
|
||||
output( "\ttestl $3,%%ecx\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||
output( "\tjz 1f\n" );
|
||||
output( "\tmovl %%eax,%%esi\n" );
|
||||
output( "\tmovl $7,%%eax\n" );
|
||||
output( "\txorl %%edx,%%edx\n" );
|
||||
output( "\txrstor 0x40(%%esp)\n" );
|
||||
output( "\tmovl %%esi,%%eax\n" );
|
||||
output( "\tjmp 3f\n" );
|
||||
output( "1:\ttestl $4,%%ecx\n" ); /* SYSCALL_HAVE_FXSAVE */
|
||||
output( "\tjz 2f\n" );
|
||||
output( "\tfxrstor 0x40(%%esp)\n" );
|
||||
output( "\tjmp 3f\n" );
|
||||
output( "2:\tfrstor 0x40(%%esp)\n" );
|
||||
output( "\tfwait\n" );
|
||||
output( "3:\tmovl 0x2c(%%esp),%%edi\n" );
|
||||
output( "\tmovl 0x30(%%esp),%%esi\n" );
|
||||
output( "\tmovl 0x34(%%esp),%%ebp\n" );
|
||||
output( "\ttestl $0x7 << 16,%%ecx\n" ); /* CONTEXT_CONTROL | CONTEXT_SEGMENTS | CONTEXT_INTEGER */
|
||||
output( "\tjnz 1f\n" );
|
||||
output( "\tmovl 0x20(%%esp),%%ebx\n" );
|
||||
output( "\tmovl 0x08(%%esp),%%ecx\n" ); /* frame->eip */
|
||||
output( "\tmovl 0x0c(%%esp),%%esp\n" ); /* frame->esp */
|
||||
output( "\tjmpl *%%ecx\n" );
|
||||
output( "1:\ttestl $0x2 << 16,%%ecx\n" ); /* CONTEXT_INTEGER */
|
||||
output( "\tjz 1f\n" );
|
||||
output( "\tmovl 0x1c(%%esp),%%eax\n" );
|
||||
output( "\tmovl 0x24(%%esp),%%ecx\n" );
|
||||
output( "\tmovl 0x28(%%esp),%%edx\n" );
|
||||
output( "1:\tmovl 0x0c(%%esp),%%ebx\n" ); /* frame->esp */
|
||||
output( "\tmovw 0x12(%%esp),%%ss\n" );
|
||||
output( "\txchgl %%ebx,%%esp\n" );
|
||||
output( "\tpushl 0x04(%%ebx)\n" ); /* frame->eflags */
|
||||
output( "\tpushl 0x10(%%ebx)\n" ); /* frame->cs */
|
||||
output( "\tpushl 0x08(%%ebx)\n" ); /* frame->eip */
|
||||
output( "\tpushl 0x14(%%ebx)\n" ); /* frame->ds */
|
||||
output( "\tmovw 0x16(%%ebx),%%es\n" );
|
||||
output( "\tmovw 0x18(%%ebx),%%fs\n" );
|
||||
output( "\tmovw 0x1a(%%ebx),%%gs\n" );
|
||||
output( "\tmovl 0x20(%%ebx),%%ebx\n" );
|
||||
output( "\tpopl %%ds\n" );
|
||||
output( "\tiret\n" );
|
||||
output( "6:\tmovl $0x%x,%%eax\n", invalid_param );
|
||||
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;
|
||||
case CPU_x86_64:
|
||||
output( "\tmovq %%gs:0x30,%%rcx\n" );
|
||||
output( "\tmovq 0x328(%%rcx),%%rcx\n" ); /* amd64_thread_data()->syscall_frame */
|
||||
output( "\tpopq 0x70(%%rcx)\n" ); /* frame->rip */
|
||||
output( "\tpushfq\n" );
|
||||
output( "\tpopq 0x80(%%rcx)\n" );
|
||||
output( "\tmovl $0,0x94(%%rcx)\n" ); /* frame->restore_flags */
|
||||
output( "%s\n", asm_globl("__wine_syscall_dispatcher_prolog_end") );
|
||||
output( "\tmovq %%rax,0x00(%%rcx)\n" );
|
||||
output( "\tmovq %%rbx,0x08(%%rcx)\n" );
|
||||
output( "\tmovq %%rdx,0x18(%%rcx)\n" );
|
||||
output( "\tmovq %%rsi,0x20(%%rcx)\n" );
|
||||
output( "\tmovq %%rdi,0x28(%%rcx)\n" );
|
||||
output( "\tmovq %%r12,0x50(%%rcx)\n" );
|
||||
output( "\tmovq %%r13,0x58(%%rcx)\n" );
|
||||
output( "\tmovq %%r14,0x60(%%rcx)\n" );
|
||||
output( "\tmovq %%r15,0x68(%%rcx)\n" );
|
||||
output( "\tmovw %%cs,0x78(%%rcx)\n" );
|
||||
output( "\tmovw %%ds,0x7a(%%rcx)\n" );
|
||||
output( "\tmovw %%es,0x7c(%%rcx)\n" );
|
||||
output( "\tmovw %%fs,0x7e(%%rcx)\n" );
|
||||
output( "\tmovq %%rsp,0x88(%%rcx)\n" );
|
||||
output( "\tmovw %%ss,0x90(%%rcx)\n" );
|
||||
output( "\tmovw %%gs,0x92(%%rcx)\n" );
|
||||
output( "\tmovq %%rbp,0x98(%%rcx)\n" );
|
||||
/* Legends of Runeterra hooks the first system call return instruction, and
|
||||
* depends on us returning to it. Adjust the return address accordingly. */
|
||||
output( "\tsubq $0xb,0x70(%%rcx)\n" );
|
||||
output( "\tmovl 0xb0(%%rcx),%%r14d\n" ); /* frame->syscall_flags */
|
||||
output( "\ttestl $3,%%r14d\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||
output( "\tjz 2f\n" );
|
||||
output( "\tmovl $7,%%eax\n" );
|
||||
output( "\txorl %%edx,%%edx\n" );
|
||||
output( "\tmovq %%rdx,0x2c0(%%rcx)\n" );
|
||||
output( "\tmovq %%rdx,0x2c8(%%rcx)\n" );
|
||||
output( "\tmovq %%rdx,0x2d0(%%rcx)\n" );
|
||||
output( "\ttestl $2,%%r14d\n" ); /* SYSCALL_HAVE_XSAVEC */
|
||||
output( "\tjz 1f\n" );
|
||||
output( "\tmovq %%rdx,0x2d8(%%rcx)\n" );
|
||||
output( "\tmovq %%rdx,0x2e0(%%rcx)\n" );
|
||||
output( "\tmovq %%rdx,0x2e8(%%rcx)\n" );
|
||||
output( "\tmovq %%rdx,0x2f0(%%rcx)\n" );
|
||||
output( "\tmovq %%rdx,0x2f8(%%rcx)\n" );
|
||||
output( "\txsavec64 0xc0(%%rcx)\n" );
|
||||
output( "\tjmp 3f\n" );
|
||||
output( "1:\txsave64 0xc0(%%rcx)\n" );
|
||||
output( "\tjmp 3f\n" );
|
||||
output( "2:\tfxsave64 0xc0(%%rcx)\n" );
|
||||
output( "3:\tleaq 0x98(%%rcx),%%rbp\n" );
|
||||
if (target_platform == PLATFORM_LINUX)
|
||||
{
|
||||
output( "\ttestl $12,%%r14d\n" ); /* SYSCALL_HAVE_PTHREAD_TEB | SYSCALL_HAVE_WRFSGSBASE */
|
||||
output( "\tjz 2f\n" );
|
||||
output( "\tmovq %%gs:0x330,%%rsi\n" ); /* amd64_thread_data()->pthread_teb */
|
||||
output( "\ttestl $8,%%r14d\n" ); /* SYSCALL_HAVE_WRFSGSBASE */
|
||||
output( "\tjz 1f\n" );
|
||||
output( "\twrfsbase %%rsi\n" );
|
||||
output( "\tjmp 2f\n" );
|
||||
output( "1:\tmov $0x1002,%%edi\n" ); /* ARCH_SET_FS */
|
||||
output( "\tmov $158,%%eax\n" ); /* SYS_arch_prctl */
|
||||
output( "\tsyscall\n" );
|
||||
output( "\tleaq -0x98(%%rbp),%%rcx\n" );
|
||||
output( "2:\n" );
|
||||
}
|
||||
output( "\tleaq 0x28(%%rsp),%%rsi\n" ); /* first argument */
|
||||
output( "\tmovq %%rcx,%%rsp\n" );
|
||||
output( "\tmovq 0x00(%%rcx),%%rax\n" );
|
||||
output( "\tmovq 0x18(%%rcx),%%rdx\n" );
|
||||
output( "\tmovl %%eax,%%ebx\n" );
|
||||
output( "\tshrl $8,%%ebx\n" );
|
||||
output( "\tandl $0x30,%%ebx\n" ); /* syscall table number */
|
||||
output( "\tmovq 0xa8(%%rcx),%%rcx\n" ); /* frame->syscall_table */
|
||||
output( "\tleaq (%%rcx,%%rbx,2),%%rbx\n" );
|
||||
output( "\tandl $0xfff,%%eax\n" ); /* syscall number */
|
||||
output( "\tcmpq 16(%%rbx),%%rax\n" ); /* table->ServiceLimit */
|
||||
output( "\tjae 5f\n" );
|
||||
output( "\tmovq 24(%%rbx),%%rcx\n" ); /* table->ArgumentTable */
|
||||
output( "\tmovzbl (%%rcx,%%rax),%%ecx\n" );
|
||||
output( "\tsubq $0x20,%%rcx\n" );
|
||||
output( "\tjbe 1f\n" );
|
||||
output( "\tsubq %%rcx,%%rsp\n" );
|
||||
output( "\tshrq $3,%%rcx\n" );
|
||||
output( "\tandq $~15,%%rsp\n\t" );
|
||||
output( "\tmovq %%rsp,%%rdi\n" );
|
||||
output( "\tcld\n" );
|
||||
output( "\trep; movsq\n" );
|
||||
output( "1:\tmovq %%r10,%%rcx\n" );
|
||||
output( "\tsubq $0x20,%%rsp\n" );
|
||||
output( "\tmovq (%%rbx),%%r10\n" ); /* table->ServiceTable */
|
||||
output( "\tcallq *(%%r10,%%rax,8)\n" );
|
||||
output( "\tleaq -0x98(%%rbp),%%rcx\n" );
|
||||
output( "2:\tmovl 0x94(%%rcx),%%edx\n" ); /* frame->restore_flags */
|
||||
if (target_platform == PLATFORM_LINUX)
|
||||
{
|
||||
output( "\ttestl $12,%%r14d\n" ); /* SYSCALL_HAVE_PTHREAD_TEB | SYSCALL_HAVE_WRFSGSBASE */
|
||||
output( "\tjz 1f\n" );
|
||||
output( "\tmovw 0x7e(%%rcx),%%fs\n" );
|
||||
output( "1:\n" );
|
||||
}
|
||||
output( "\ttestl $0x48,%%edx\n" ); /* CONTEXT_FLOATING_POINT | CONTEXT_XSTATE */
|
||||
output( "\tjz 4f\n" );
|
||||
output( "\ttestl $3,%%r14d\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||
output( "\tjz 3f\n" );
|
||||
output( "\tmovq %%rax,%%r11\n" );
|
||||
output( "\tmovl $7,%%eax\n" );
|
||||
output( "\txorl %%edx,%%edx\n" );
|
||||
output( "\txrstor64 0xc0(%%rcx)\n" );
|
||||
output( "\tmovq %%r11,%%rax\n" );
|
||||
output( "\tmovl 0x94(%%rcx),%%edx\n" );
|
||||
output( "\tjmp 4f\n" );
|
||||
output( "3:\tfxrstor64 0xc0(%%rcx)\n" );
|
||||
output( "4:\tmovq 0x98(%%rcx),%%rbp\n" );
|
||||
output( "\tmovq 0x68(%%rcx),%%r15\n" );
|
||||
output( "\tmovq 0x60(%%rcx),%%r14\n" );
|
||||
output( "\tmovq 0x58(%%rcx),%%r13\n" );
|
||||
output( "\tmovq 0x50(%%rcx),%%r12\n" );
|
||||
output( "\tmovq 0x28(%%rcx),%%rdi\n" );
|
||||
output( "\tmovq 0x20(%%rcx),%%rsi\n" );
|
||||
output( "\tmovq 0x08(%%rcx),%%rbx\n" );
|
||||
output( "\ttestl $0x3,%%edx\n" ); /* CONTEXT_CONTROL | CONTEXT_INTEGER */
|
||||
output( "\tjnz 1f\n" );
|
||||
output( "\tmovq 0x88(%%rcx),%%rsp\n" );
|
||||
output( "\tjmpq *0x70(%%rcx)\n" ); /* frame->rip */
|
||||
output( "1:\tleaq 0x70(%%rcx),%%rsp\n" );
|
||||
output( "\ttestl $0x2,%%edx\n" ); /* CONTEXT_INTEGER */
|
||||
output( "\tjz 1f\n" );
|
||||
output( "\tmovq 0x00(%%rcx),%%rax\n" );
|
||||
output( "\tmovq 0x18(%%rcx),%%rdx\n" );
|
||||
output( "\tmovq 0x30(%%rcx),%%r8\n" );
|
||||
output( "\tmovq 0x38(%%rcx),%%r9\n" );
|
||||
output( "\tmovq 0x40(%%rcx),%%r10\n" );
|
||||
output( "\tmovq 0x48(%%rcx),%%r11\n" );
|
||||
output( "\tmovq 0x10(%%rcx),%%rcx\n" );
|
||||
output( "1:\tiretq\n" );
|
||||
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 0xb0(%%rcx),%%r14d\n" ); /* frame->syscall_flags */
|
||||
output( "\tmovq %%rdx,%%rax\n" );
|
||||
output( "\tjmp 2b\n" );
|
||||
break;
|
||||
case CPU_ARM:
|
||||
output( "\tmrc p15, 0, r1, c13, c0, 2\n" ); /* NtCurrentTeb() */
|
||||
output( "\tldr r1, [r1, #0x1d8]\n" ); /* arm_thread_data()->syscall_frame */
|
||||
output( "\tadd r0, r1, #0x10\n" );
|
||||
output( "\tstm r0, {r4-r12,lr}\n" );
|
||||
output( "\tstr sp, [r1, #0x38]\n" );
|
||||
output( "\tstr r3, [r1, #0x3c]\n" );
|
||||
output( "\tmrs r0, CPSR\n" );
|
||||
output( "\tbfi r0, lr, #5, #1\n" ); /* set thumb bit */
|
||||
output( "\tstr r0, [r1, #0x40]\n" );
|
||||
output( "\tmov r0, #0\n" );
|
||||
output( "\tstr r0, [r1, #0x44]\n" ); /* frame->restore_flags */
|
||||
if (strcmp( float_abi_option, "soft" ))
|
||||
{
|
||||
output( "\tvmrs r0, fpscr\n" );
|
||||
output( "\tstr r0, [r1, #0x48]\n" );
|
||||
output( "\tadd r0, r1, #0x60\n" );
|
||||
output( "\tvstm r0, {d0-d15}\n" );
|
||||
}
|
||||
output( "\tmov r6, sp\n" );
|
||||
output( "\tmov sp, r1\n" );
|
||||
output( "\tmov r8, r1\n" );
|
||||
output( "\tldr r5, [r1, #0x50]\n"); /* frame->syscall_table */
|
||||
output( "\tubfx r4, ip, #12, #2\n" ); /* syscall table number */
|
||||
output( "\tbfc ip, #12, #20\n" ); /* syscall number */
|
||||
output( "\tadd r4, r5, r4, lsl #4\n" );
|
||||
output( "\tldr r5, [r4, #8]\n" ); /* table->ServiceLimit */
|
||||
output( "\tcmp ip, r5\n" );
|
||||
output( "\tbcs 5f\n" );
|
||||
output( "\tldr r5, [r4, #12]\n" ); /* table->ArgumentTable */
|
||||
output( "\tldrb r5, [r5, ip]\n" );
|
||||
output( "\tcmp r5, #16\n" );
|
||||
output( "\tit le\n" );
|
||||
output( "\tmovle r5, #16\n" );
|
||||
output( "\tsub r0, sp, r5\n" );
|
||||
output( "\tand r0, #~7\n" );
|
||||
output( "\tmov sp, r0\n" );
|
||||
output( "2:\tsubs r5, r5, #4\n" );
|
||||
output( "\tldr r0, [r6, r5]\n" );
|
||||
output( "\tstr r0, [sp, r5]\n" );
|
||||
output( "\tbgt 2b\n" );
|
||||
output( "\tpop {r0-r3}\n" ); /* first 4 args are in registers */
|
||||
output( "\tldr r5, [r4]\n"); /* table->ServiceTable */
|
||||
output( "\tldr ip, [r5, ip, lsl #2]\n");
|
||||
output( "\tblx ip\n");
|
||||
output( "4:\tldr ip, [r8, #0x44]\n" ); /* frame->restore_flags */
|
||||
if (strcmp( float_abi_option, "soft" ))
|
||||
{
|
||||
output( "\ttst ip, #4\n" ); /* CONTEXT_FLOATING_POINT */
|
||||
output( "\tbeq 3f\n" );
|
||||
output( "\tldr r4, [r8, #0x48]\n" );
|
||||
output( "\tvmsr fpscr, r4\n" );
|
||||
output( "\tadd r4, r8, #0x60\n" );
|
||||
output( "\tvldm r4, {d0-d15}\n" );
|
||||
output( "3:\n" );
|
||||
}
|
||||
output( "\ttst ip, #2\n" ); /* CONTEXT_INTEGER */
|
||||
output( "\tit ne\n" );
|
||||
output( "\tldmne r8, {r0-r3}\n" );
|
||||
output( "\tldr lr, [r8, #0x3c]\n" );
|
||||
output( "\tldr sp, [r8, #0x38]\n" );
|
||||
output( "\tadd r8, r8, #0x10\n" );
|
||||
output( "\tldm r8, {r4-r12,pc}\n" );
|
||||
output( "5:\tmovw r0, #0x%x\n", invalid_param & 0xffff );
|
||||
output( "\tmovt r0, #0x%x\n", invalid_param >> 16 );
|
||||
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" );
|
||||
break;
|
||||
case CPU_ARM64:
|
||||
/* FIXME: use x18 directly instead */
|
||||
output( "\tstp x0, x1, [sp, #-96]!\n" );
|
||||
output( "\tstp x2, x3, [sp, #16]\n" );
|
||||
output( "\tstp x4, x5, [sp, #32]\n" );
|
||||
output( "\tstp x6, x7, [sp, #48]\n" );
|
||||
output( "\tstp x8, x9, [sp, #64]\n" );
|
||||
output( "\tstr x30, [sp, #80]\n" );
|
||||
output( "\tbl %s\n", asm_name("NtCurrentTeb") );
|
||||
output( "\tmov x18, x0\n" );
|
||||
output( "\tldp x2, x3, [sp, #16]\n" );
|
||||
output( "\tldp x4, x5, [sp, #32]\n" );
|
||||
output( "\tldp x6, x7, [sp, #48]\n" );
|
||||
output( "\tldp x8, x9, [sp, #64]\n" );
|
||||
output( "\tldr x30, [sp, #80]\n" );
|
||||
output( "\tldp x0, x1, [sp], #96\n" );
|
||||
|
||||
output( "\tldr x10, [x18, #0x2f8]\n" ); /* arm64_thread_data()->syscall_frame */
|
||||
output( "\tstp x18, x19, [x10, #0x90]\n" );
|
||||
output( "\tstp x20, x21, [x10, #0xa0]\n" );
|
||||
output( "\tstp x22, x23, [x10, #0xb0]\n" );
|
||||
output( "\tstp x24, x25, [x10, #0xc0]\n" );
|
||||
output( "\tstp x26, x27, [x10, #0xd0]\n" );
|
||||
output( "\tstp x28, x29, [x10, #0xe0]\n" );
|
||||
output( "\tmov x19, sp\n" );
|
||||
output( "\tstp x9, x19, [x10, #0xf0]\n" );
|
||||
output( "\tmrs x9, NZCV\n" );
|
||||
output( "\tstp x30, x9, [x10, #0x100]\n" );
|
||||
output( "\tmrs x9, FPCR\n" );
|
||||
output( "\tstr w9, [x10, #0x128]\n" );
|
||||
output( "\tmrs x9, FPSR\n" );
|
||||
output( "\tstr w9, [x10, #0x12c]\n" );
|
||||
output( "\tstp q0, q1, [x10, #0x130]\n" );
|
||||
output( "\tstp q2, q3, [x10, #0x150]\n" );
|
||||
output( "\tstp q4, q5, [x10, #0x170]\n" );
|
||||
output( "\tstp q6, q7, [x10, #0x190]\n" );
|
||||
output( "\tstp q8, q9, [x10, #0x1b0]\n" );
|
||||
output( "\tstp q10, q11, [x10, #0x1d0]\n" );
|
||||
output( "\tstp q12, q13, [x10, #0x1f0]\n" );
|
||||
output( "\tstp q14, q15, [x10, #0x210]\n" );
|
||||
output( "\tstp q16, q17, [x10, #0x230]\n" );
|
||||
output( "\tstp q18, q19, [x10, #0x250]\n" );
|
||||
output( "\tstp q20, q21, [x10, #0x270]\n" );
|
||||
output( "\tstp q22, q23, [x10, #0x290]\n" );
|
||||
output( "\tstp q24, q25, [x10, #0x2b0]\n" );
|
||||
output( "\tstp q26, q27, [x10, #0x2d0]\n" );
|
||||
output( "\tstp q28, q29, [x10, #0x2f0]\n" );
|
||||
output( "\tstp q30, q31, [x10, #0x310]\n" );
|
||||
output( "\tmov sp, x10\n" );
|
||||
output( "\tand x20, x8, #0xfff\n" ); /* syscall number */
|
||||
output( "\tubfx x21, x8, #12, #2\n" ); /* syscall table number */
|
||||
output( "\tldr x16, [x10, #0x118]\n" );/* frame->syscall_table */
|
||||
output( "\tadd x21, x16, x21, lsl #5\n" );
|
||||
output( "\tldr x16, [x21, #16]\n" ); /* table->ServiceLimit */
|
||||
output( "\tcmp x20, x16\n" );
|
||||
output( "\tbcs 4f\n" );
|
||||
output( "\tmov x22, sp\n" );
|
||||
output( "\tldr x16, [x21, #24]\n" ); /* table->ArgumentTable */
|
||||
output( "\tldrb w9, [x16, x20]\n" );
|
||||
output( "\tsubs x9, x9, #64\n" );
|
||||
output( "\tbls 2f\n" );
|
||||
output( "\tsub sp, sp, x9\n" );
|
||||
output( "\ttbz x9, #3, 1f\n" );
|
||||
output( "\tsub sp, sp, #8\n" );
|
||||
output( "1:\tsub x9, x9, #8\n" );
|
||||
output( "\tldr x10, [x19, x9]\n" );
|
||||
output( "\tstr x10, [sp, x9]\n" );
|
||||
output( "\tcbnz x9, 1b\n" );
|
||||
output( "2:\tldr x16, [x21]\n" ); /* table->ServiceTable */
|
||||
output( "\tldr x16, [x16, x20, lsl 3]\n" );
|
||||
output( "\tblr x16\n" );
|
||||
output( "\tmov sp, x22\n" );
|
||||
output( "3:\tldp x18, x19, [sp, #0x90]\n" );
|
||||
output( "\tldp x20, x21, [sp, #0xa0]\n" );
|
||||
output( "\tldp x22, x23, [sp, #0xb0]\n" );
|
||||
output( "\tldp x24, x25, [sp, #0xc0]\n" );
|
||||
output( "\tldp x26, x27, [sp, #0xd0]\n" );
|
||||
output( "\tldp x28, x29, [sp, #0xe0]\n" );
|
||||
output( "\tldr w16, [sp, #0x10c]\n" ); /* frame->restore_flags */
|
||||
output( "\ttbz x16, #2, 1f\n" ); /* CONTEXT_FLOATING_POINT */
|
||||
output( "\tldp q0, q1, [sp, #0x130]\n" );
|
||||
output( "\tldp q2, q3, [sp, #0x150]\n" );
|
||||
output( "\tldp q4, q5, [sp, #0x170]\n" );
|
||||
output( "\tldp q6, q7, [sp, #0x190]\n" );
|
||||
output( "\tldp q8, q9, [sp, #0x1b0]\n" );
|
||||
output( "\tldp q10, q11, [sp, #0x1d0]\n" );
|
||||
output( "\tldp q12, q13, [sp, #0x1f0]\n" );
|
||||
output( "\tldp q14, q15, [sp, #0x210]\n" );
|
||||
output( "\tldp q16, q17, [sp, #0x230]\n" );
|
||||
output( "\tldp q18, q19, [sp, #0x250]\n" );
|
||||
output( "\tldp q20, q21, [sp, #0x270]\n" );
|
||||
output( "\tldp q22, q23, [sp, #0x290]\n" );
|
||||
output( "\tldp q24, q25, [sp, #0x2b0]\n" );
|
||||
output( "\tldp q26, q27, [sp, #0x2d0]\n" );
|
||||
output( "\tldp q28, q29, [sp, #0x2f0]\n" );
|
||||
output( "\tldp q30, q31, [sp, #0x310]\n" );
|
||||
output( "\tldr w9, [sp, #0x128]\n" );
|
||||
output( "\tmsr FPCR, x9\n" );
|
||||
output( "\tldr w9, [sp, #0x12c]\n" );
|
||||
output( "\tmsr FPSR, x9\n" );
|
||||
output( "1:\ttbz x16, #1, 1f\n" ); /* CONTEXT_INTEGER */
|
||||
output( "\tldp x0, x1, [sp, #0x00]\n" );
|
||||
output( "\tldp x2, x3, [sp, #0x10]\n" );
|
||||
output( "\tldp x4, x5, [sp, #0x20]\n" );
|
||||
output( "\tldp x6, x7, [sp, #0x30]\n" );
|
||||
output( "\tldp x8, x9, [sp, #0x40]\n" );
|
||||
output( "\tldp x10, x11, [sp, #0x50]\n" );
|
||||
output( "\tldp x12, x13, [sp, #0x60]\n" );
|
||||
output( "\tldp x14, x15, [sp, #0x70]\n" );
|
||||
output( "1:\tldp x16, x17, [sp, #0x100]\n" );
|
||||
output( "\tmsr NZCV, x17\n" );
|
||||
output( "\tldp x30, x17, [sp, #0xf0]\n" );
|
||||
output( "\tmov sp, x17\n" );
|
||||
output( "\tret x16\n" );
|
||||
output( "4:\tmov x0, #0x%x\n", invalid_param & 0xffff0000 );
|
||||
output( "\tmovk x0, #0x%x\n", invalid_param & 0x0000ffff );
|
||||
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;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
output_cfi( ".cfi_endproc" );
|
||||
output_function_size( "__wine_syscall_dispatcher" );
|
||||
}
|
||||
|
||||
|
||||
/* output the functions for system calls */
|
||||
void output_syscalls( DLLSPEC *spec )
|
||||
{
|
||||
|
@ -1905,8 +1441,6 @@ void output_syscalls( DLLSPEC *spec )
|
|||
|
||||
if (unix_lib)
|
||||
{
|
||||
output_syscall_dispatcher();
|
||||
|
||||
output( "\t.data\n" );
|
||||
output( "\t.align %d\n", get_alignment( get_ptr_size() ) );
|
||||
output( "%s\n", asm_globl("__wine_syscall_table") );
|
||||
|
|
Loading…
Reference in a new issue