ntdll: Store the syscall table in the syscall frame on all platforms.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-08-25 15:15:01 +02:00
parent 77f5e2963f
commit 847db3c1d3
8 changed files with 122 additions and 107 deletions

View file

@ -115,6 +115,11 @@ SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock = NULL;
static NTSTATUS (CDECL *p__wine_set_unix_funcs)( int version, const struct unix_funcs *funcs );
extern SYSTEM_SERVICE_TABLE __wine_syscall_table DECLSPEC_HIDDEN;
SYSTEM_SERVICE_TABLE KeServiceDescriptorTable[4];
#ifdef __GNUC__
static void fatal_error( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
#endif
@ -1939,6 +1944,7 @@ static void start_main_thread(void)
NtCreateKeyedEvent( &keyed_event, GENERIC_READ | GENERIC_WRITE, NULL, 0 );
load_ntdll();
if (main_image_info.Machine != current_machine) load_wow64_ntdll( main_image_info.Machine );
KeServiceDescriptorTable[0] = __wine_syscall_table;
status = p__wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION, &unix_funcs );
if (status == STATUS_REVISION_MISMATCH)
{

View file

@ -192,10 +192,12 @@ struct syscall_frame
DWORD restore_flags; /* 044 */
DWORD fpscr; /* 048 */
struct syscall_frame *prev_frame; /* 04c */
ULONGLONG d[32]; /* 050 */
SYSTEM_SERVICE_TABLE *syscall_table; /* 050 */
DWORD align[3]; /* 054 */
ULONGLONG d[32]; /* 060 */
};
C_ASSERT( sizeof( struct syscall_frame ) == 0x150);
C_ASSERT( sizeof( struct syscall_frame ) == 0x160);
struct arm_thread_data
{
@ -607,6 +609,7 @@ NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void
callback_frame.frame.sp = (ULONG_PTR)args_data;
callback_frame.frame.pc = (ULONG_PTR)pKiUserCallbackDispatcher;
callback_frame.frame.restore_flags = CONTEXT_INTEGER;
callback_frame.frame.syscall_table = frame->syscall_table;
callback_frame.frame.prev_frame = frame;
arm_thread_data()->syscall_frame = &callback_frame.frame;
@ -993,6 +996,7 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B
frame->r0 = (DWORD)ctx;
frame->prev_frame = NULL;
frame->restore_flags |= CONTEXT_INTEGER;
frame->syscall_table = KeServiceDescriptorTable;
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
__wine_syscall_dispatcher_return( frame, 0 );
@ -1009,7 +1013,7 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
/* set syscall frame */
"ldr r6, [r3, #0x1d8]\n\t" /* arm_thread_data()->syscall_frame */
"cbnz r6, 1f\n\t"
"sub r6, sp, #0x150\n\t" /* sizeof(struct syscall_frame) */
"sub r6, sp, #0x160\n\t" /* sizeof(struct syscall_frame) */
"str r6, [r3, #0x1d8]\n\t" /* arm_thread_data()->syscall_frame */
"1:\tmov sp, r6\n\t"
"bl " __ASM_NAME("call_init_thunk") )

View file

@ -142,12 +142,14 @@ struct syscall_frame
ULONG cpsr; /* 108 */
ULONG restore_flags; /* 10c */
struct syscall_frame *prev_frame; /* 110 */
ULONG fpcr; /* 118 */
ULONG fpsr; /* 11c */
NEON128 v[32]; /* 120 */
SYSTEM_SERVICE_TABLE *syscall_table; /* 118 */
ULONG64 align; /* 120 */
ULONG fpcr; /* 128 */
ULONG fpsr; /* 12c */
NEON128 v[32]; /* 130 */
};
C_ASSERT( sizeof( struct syscall_frame ) == 0x320 );
C_ASSERT( sizeof( struct syscall_frame ) == 0x330 );
struct arm64_thread_data
{
@ -756,6 +758,7 @@ NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void
callback_frame.frame.sp = (ULONG_PTR)args_data;
callback_frame.frame.pc = (ULONG_PTR)pKiUserCallbackDispatcher;
callback_frame.frame.restore_flags = CONTEXT_INTEGER;
callback_frame.frame.syscall_table = frame->syscall_table;
callback_frame.frame.prev_frame = frame;
arm64_thread_data()->syscall_frame = &callback_frame.frame;
@ -1186,6 +1189,7 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B
frame->x[18] = (ULONG64)teb;
frame->prev_frame = NULL;
frame->restore_flags |= CONTEXT_INTEGER;
frame->syscall_table = KeServiceDescriptorTable;
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
__wine_syscall_dispatcher_return( frame, 0 );
@ -1203,7 +1207,7 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
/* set syscall frame */
"ldr x8, [x3, #0x2f8]\n\t" /* arm64_thread_data()->syscall_frame */
"cbnz x8, 1f\n\t"
"sub x8, sp, #0x320\n\t" /* sizeof(struct syscall_frame) */
"sub x8, sp, #0x330\n\t" /* sizeof(struct syscall_frame) */
"str x8, [x3, #0x2f8]\n\t" /* arm64_thread_data()->syscall_frame */
"1:\tmov sp, x8\n\t"
"bl " __ASM_NAME("call_init_thunk") )

View file

@ -463,26 +463,27 @@ enum i386_trap_code
struct syscall_frame
{
DWORD restore_flags; /* 000 */
DWORD eflags; /* 004 */
DWORD eip; /* 008 */
DWORD esp; /* 00c */
WORD cs; /* 010 */
WORD ss; /* 012 */
WORD ds; /* 014 */
WORD es; /* 016 */
WORD fs; /* 018 */
WORD gs; /* 01a */
DWORD eax; /* 01c */
DWORD ebx; /* 020 */
DWORD ecx; /* 024 */
DWORD edx; /* 028 */
DWORD edi; /* 02c */
DWORD esi; /* 030 */
DWORD ebp; /* 034 */
DWORD syscall_flags; /* 038 */
struct syscall_frame *prev_frame; /* 03c */
union /* 040 */
WORD syscall_flags; /* 000 */
WORD restore_flags; /* 002 */
DWORD eflags; /* 004 */
DWORD eip; /* 008 */
DWORD esp; /* 00c */
WORD cs; /* 010 */
WORD ss; /* 012 */
WORD ds; /* 014 */
WORD es; /* 016 */
WORD fs; /* 018 */
WORD gs; /* 01a */
DWORD eax; /* 01c */
DWORD ebx; /* 020 */
DWORD ecx; /* 024 */
DWORD edx; /* 028 */
DWORD edi; /* 02c */
DWORD esi; /* 030 */
DWORD ebp; /* 034 */
SYSTEM_SERVICE_TABLE *syscall_table; /* 038 */
struct syscall_frame *prev_frame; /* 03c */
union /* 040 */
{
XSAVE_FORMAT xsave;
FLOATING_SAVE_AREA fsave;
@ -490,7 +491,7 @@ struct syscall_frame
/* Leave space for the whole set of YMM registers. They're not used in
* 32-bit mode, but some processors fault if they're not in writable memory.
*/
DECLSPEC_ALIGN(64) XSTATE xstate; /* 240 */
DECLSPEC_ALIGN(64) XSTATE xstate; /* 240 */
};
C_ASSERT( sizeof(struct syscall_frame) == 0x380 );
@ -873,7 +874,7 @@ NTSTATUS signal_set_full_context( CONTEXT *context )
NTSTATUS status = NtSetContextThread( GetCurrentThread(), context );
if (!status && (context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
x86_thread_data()->syscall_frame->restore_flags |= CONTEXT_INTEGER;
x86_thread_data()->syscall_frame->restore_flags |= LOWORD(CONTEXT_INTEGER);
return status;
}
@ -1617,6 +1618,7 @@ NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void
callback_frame.frame.eip = (ULONG_PTR)pKiUserCallbackDispatcher;
callback_frame.frame.eflags = 0x202;
callback_frame.frame.syscall_flags = frame->syscall_flags;
callback_frame.frame.syscall_table = frame->syscall_table;
callback_frame.frame.prev_frame = frame;
x86_thread_data()->syscall_frame = &callback_frame.frame;
@ -1779,7 +1781,7 @@ static BOOL handle_syscall_trap( ucontext_t *sigcontext )
frame->eip = *(ULONG *)ESP_sig( sigcontext );
frame->eflags = EFL_sig(sigcontext);
frame->restore_flags = CONTEXT_CONTROL;
frame->restore_flags = LOWORD(CONTEXT_CONTROL);
EIP_sig( sigcontext ) = (ULONG)__wine_syscall_dispatcher_prolog_end;
ECX_sig( sigcontext ) = (ULONG)frame;
@ -2420,7 +2422,8 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B
frame->eip = (DWORD)pLdrInitializeThunk;
frame->prev_frame = NULL;
frame->syscall_flags = syscall_flags;
frame->restore_flags |= CONTEXT_INTEGER;
frame->syscall_table = KeServiceDescriptorTable;
frame->restore_flags |= LOWORD(CONTEXT_INTEGER);
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
__wine_syscall_dispatcher_return( frame, 0 );

View file

@ -327,8 +327,9 @@ struct syscall_frame
DWORD restore_flags; /* 0094 */
ULONG64 rbp; /* 0098 */
struct syscall_frame *prev_frame; /* 00a0 */
DWORD syscall_flags; /* 00a8 */
DWORD align[5]; /* 00ac */
SYSTEM_SERVICE_TABLE *syscall_table; /* 00a8 */
DWORD syscall_flags; /* 00b0 */
DWORD align[3]; /* 00b4 */
XMM_SAVE_AREA32 xsave; /* 00c0 */
DECLSPEC_ALIGN(64) XSTATE xstate; /* 02c0 */
};
@ -2318,6 +2319,7 @@ NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void
callback_frame.frame.restore_flags = CONTEXT_CONTROL | CONTEXT_INTEGER;
callback_frame.frame.prev_frame = frame;
callback_frame.frame.syscall_flags = frame->syscall_flags;
callback_frame.frame.syscall_table = frame->syscall_table;
amd64_thread_data()->syscall_frame = &callback_frame.frame;
__wine_syscall_dispatcher_return( &callback_frame.frame, 0 );
@ -3043,6 +3045,7 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B
frame->prev_frame = NULL;
frame->restore_flags |= CONTEXT_INTEGER;
frame->syscall_flags = syscall_flags;
frame->syscall_table = KeServiceDescriptorTable;
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
__wine_syscall_dispatcher_return( frame, 0 );

View file

@ -26,6 +26,8 @@ typedef UINT64 unixlib_handle_t;
extern NTSTATUS WINAPI __wine_unix_call( unixlib_handle_t handle, unsigned int code, void *args );
extern SYSTEM_SERVICE_TABLE KeServiceDescriptorTable[4];
/* some useful helpers from ntdll */
extern DWORD ntdll_umbstowcs( const char *src, DWORD srclen, WCHAR *dst, DWORD dstlen );
extern int ntdll_wcstoumbs( const WCHAR *src, DWORD srclen, char *dst, DWORD dstlen, BOOL strict );

View file

@ -3761,6 +3761,14 @@ typedef struct
} SYSTEM_DLL_INIT_BLOCK;
#endif
typedef struct
{
ULONG_PTR *ServiceTable;
ULONG_PTR *CounterTable;
ULONG_PTR ServiceLimit;
BYTE *ArgumentTable;
} SYSTEM_SERVICE_TABLE;
/***********************************************************************
* Function declarations
*/

View file

@ -1434,7 +1434,7 @@ static void output_syscall_dispatcher(void)
{
case CPU_x86:
output( "\tmovl %%fs:0x1f8,%%ecx\n" ); /* x86_thread_data()->syscall_frame */
output( "\tmovl $0,0x00(%%ecx)\n" ); /* frame->restore_flags */
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 */
@ -1453,29 +1453,23 @@ static void output_syscall_dispatcher(void)
output( "\tmovl %%ebp,0x34(%%ecx)\n" );
output( "\tleal 0x34(%%ecx),%%ebp\n" );
output( "\tleal 4(%%esp),%%esi\n" ); /* first argument */
output( "\tmovl %%eax,%%edx\n" );
output( "\tshrl $8,%%edx\n" );
output( "\tandl $0x30,%%edx\n" ); /* syscall table number */
if (UsePIC)
{
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
output( "1:\tleal %s-1b(%%eax,%%edx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
needs_get_pc_thunk = 1;
}
else output( "\tleal %s(%%edx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
output( "\ttestl $3,0x38(%%ecx)\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
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,0x38(%%ecx)\n" ); /* SYSCALL_HAVE_XSAVEC */
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,0x38(%%ecx)\n" ); /* SYSCALL_HAVE_FXSAVE */
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" );
@ -1497,10 +1491,10 @@ static void output_syscall_dispatcher(void)
output( "\trep; movsl\n" );
output( "\tcall *(%%eax,%%edx,4)\n" );
output( "\tleal -0x34(%%ebp),%%esp\n" );
output( "5:\tmovl (%%esp),%%ecx\n" ); /* frame->restore_flags */
output( "\ttestl $0x68,%%ecx\n" ); /* CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS | CONTEXT_XSAVE */
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,0x38(%%esp)\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
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" );
@ -1508,7 +1502,7 @@ static void output_syscall_dispatcher(void)
output( "\txrstor 0x40(%%esp)\n" );
output( "\tmovl %%esi,%%eax\n" );
output( "\tjmp 3f\n" );
output( "1:\ttestl $4,0x38(%%esp)\n" ); /* SYSCALL_HAVE_FXSAVE */
output( "1:\ttestl $4,%%ecx\n" ); /* SYSCALL_HAVE_FXSAVE */
output( "\tjz 2f\n" );
output( "\tfxrstor 0x40(%%esp)\n" );
output( "\tjmp 3f\n" );
@ -1517,13 +1511,13 @@ static void output_syscall_dispatcher(void)
output( "3:\tmovl 0x2c(%%esp),%%edi\n" );
output( "\tmovl 0x30(%%esp),%%esi\n" );
output( "\tmovl 0x34(%%esp),%%ebp\n" );
output( "\ttestl $0x7,%%ecx\n" ); /* CONTEXT_CONTROL | CONTEXT_SEGMENTS | CONTEXT_INTEGER */
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,%%ecx\n" ); /* CONTEXT_INTEGER */
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" );
@ -1576,7 +1570,7 @@ static void output_syscall_dispatcher(void)
/* 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 0xa8(%%rcx),%%r14d\n" ); /* frame->syscall_flags */
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" );
@ -1619,7 +1613,7 @@ static void output_syscall_dispatcher(void)
output( "\tmovl %%eax,%%ebx\n" );
output( "\tshrl $8,%%ebx\n" );
output( "\tandl $0x30,%%ebx\n" ); /* syscall table number */
output( "\tleaq %s(%%rip),%%rcx\n", asm_name("KeServiceDescriptorTable") );
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 */
@ -1685,7 +1679,7 @@ static void output_syscall_dispatcher(void)
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 0xa8(%%rcx),%%r14d\n" ); /* frame->syscall_flags */
output( "\tmovl 0xb0(%%rcx),%%r14d\n" ); /* frame->syscall_flags */
output( "\tmovq %%rdx,%%rax\n" );
output( "\tjmp 2b\n" );
break;
@ -1705,14 +1699,13 @@ static void output_syscall_dispatcher(void)
{
output( "\tvmrs r0, fpscr\n" );
output( "\tstr r0, [r1, #0x48]\n" );
output( "\tadd r0, r1, #0x50\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, 6f\n");
if (UsePIC) output( "1:\tadd r5, pc\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" );
@ -1742,7 +1735,7 @@ static void output_syscall_dispatcher(void)
output( "\tbeq 3f\n" );
output( "\tldr r4, [r8, #0x48]\n" );
output( "\tvmsr fpscr, r4\n" );
output( "\tadd r4, r8, #0x50\n" );
output( "\tadd r4, r8, #0x60\n" );
output( "\tvldm r4, {d0-d15}\n" );
output( "3:\n" );
}
@ -1760,10 +1753,6 @@ static void output_syscall_dispatcher(void)
output( "\tmov r8, r0\n" );
output( "\tmov r0, r1\n" );
output( "\tb 4b\n" );
if (UsePIC)
output( "6:\t.long %s-1b-%u\n", asm_name("KeServiceDescriptorTable"), thumb_mode ? 4 : 8 );
else
output( "6:\t.long %s\n", asm_name("KeServiceDescriptorTable") );
break;
case CPU_ARM64:
/* FIXME: use x18 directly instead */
@ -1794,30 +1783,29 @@ static void output_syscall_dispatcher(void)
output( "\tmrs x9, NZCV\n" );
output( "\tstp x30, x9, [x10, #0x100]\n" );
output( "\tmrs x9, FPCR\n" );
output( "\tstr w9, [x10, #0x118]\n" );
output( "\tstr w9, [x10, #0x128]\n" );
output( "\tmrs x9, FPSR\n" );
output( "\tstr w9, [x10, #0x11c]\n" );
output( "\tstp q0, q1, [x10, #0x120]\n" );
output( "\tstp q2, q3, [x10, #0x140]\n" );
output( "\tstp q4, q5, [x10, #0x160]\n" );
output( "\tstp q6, q7, [x10, #0x180]\n" );
output( "\tstp q8, q9, [x10, #0x1a0]\n" );
output( "\tstp q10, q11, [x10, #0x1c0]\n" );
output( "\tstp q12, q13, [x10, #0x1e0]\n" );
output( "\tstp q14, q15, [x10, #0x200]\n" );
output( "\tstp q16, q17, [x10, #0x220]\n" );
output( "\tstp q18, q19, [x10, #0x240]\n" );
output( "\tstp q20, q21, [x10, #0x260]\n" );
output( "\tstp q22, q23, [x10, #0x280]\n" );
output( "\tstp q24, q25, [x10, #0x2a0]\n" );
output( "\tstp q26, q27, [x10, #0x2c0]\n" );
output( "\tstp q28, q29, [x10, #0x2e0]\n" );
output( "\tstp q30, q31, [x10, #0x300]\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( "\tadrp x16, %s\n", arm64_page(asm_name("KeServiceDescriptorTable")) );
output( "\tadd x16, x16, #%s\n", arm64_pageoff(asm_name("KeServiceDescriptorTable")) );
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" );
@ -1846,25 +1834,25 @@ static void output_syscall_dispatcher(void)
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, #0x120]\n" );
output( "\tldp q2, q3, [sp, #0x140]\n" );
output( "\tldp q4, q5, [sp, #0x160]\n" );
output( "\tldp q6, q7, [sp, #0x180]\n" );
output( "\tldp q8, q9, [sp, #0x1a0]\n" );
output( "\tldp q10, q11, [sp, #0x1c0]\n" );
output( "\tldp q12, q13, [sp, #0x1e0]\n" );
output( "\tldp q14, q15, [sp, #0x200]\n" );
output( "\tldp q16, q17, [sp, #0x220]\n" );
output( "\tldp q18, q19, [sp, #0x240]\n" );
output( "\tldp q20, q21, [sp, #0x260]\n" );
output( "\tldp q22, q23, [sp, #0x280]\n" );
output( "\tldp q24, q25, [sp, #0x2a0]\n" );
output( "\tldp q26, q27, [sp, #0x2c0]\n" );
output( "\tldp q28, q29, [sp, #0x2e0]\n" );
output( "\tldp q30, q31, [sp, #0x300]\n" );
output( "\tldr w9, [sp, #0x118]\n" );
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, #0x11c]\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" );
@ -1921,11 +1909,8 @@ void output_syscalls( DLLSPEC *spec )
output( "\t.data\n" );
output( "\t.align %d\n", get_alignment( get_ptr_size() ) );
output( "%s\n", asm_globl("KeServiceDescriptorTable") );
output( "%s\n", asm_globl("__wine_syscall_table") );
output( "\t%s .Lsyscall_table, 0, %u, .Lsyscall_args\n", get_asm_ptr_keyword(), count );
output( "\t%s 0, 0, 0, 0\n", get_asm_ptr_keyword() );
output( "\t%s 0, 0, 0, 0\n", get_asm_ptr_keyword() );
output( "\t%s 0, 0, 0, 0\n", get_asm_ptr_keyword() );
output( ".Lsyscall_table:\n" );
for (i = 0; i < count; i++)
output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name( get_link_name( syscalls[i] )));