diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index de0f7deb150..e1e5b535bef 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -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__ */ diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index 2fcc1bb5739..a3cee8e7e9e 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -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.@) */ diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 5638975e337..7067435bf0b 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -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.@) */ diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index eab9932f52f..8065f1b8220 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -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__ */ diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 0228952d3b3..6a158578143 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -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") );