Module: wine Branch: master Commit: d9adc902f88445fb1a33825775884de394124d71 URL: https://source.winehq.org/git/wine.git/?a=commit;h=d9adc902f88445fb1a3382577...
Author: Alexandre Julliard julliard@winehq.org Date: Fri Sep 27 12:39:49 2019 +0200
rpcrt4: Add stubless proxy support for ARM64.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/rpcrt4/cproxy.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ dlls/rpcrt4/cstub.c | 17 +++++++++++++++++ dlls/rpcrt4/ndr_stubless.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+)
diff --git a/dlls/rpcrt4/cproxy.c b/dlls/rpcrt4/cproxy.c index 3b9467735b..968c7b5156 100644 --- a/dlls/rpcrt4/cproxy.c +++ b/dlls/rpcrt4/cproxy.c @@ -196,6 +196,50 @@ static inline void init_thunk( struct thunk *thunk, unsigned int index ) thunk->func = call_stubless_func; }
+#elif defined(__aarch64__) + +extern void call_stubless_func(void); +__ASM_GLOBAL_FUNC( call_stubless_func, + "stp x29, x30, [sp, #-0x90]!\n\t" + "mov x29, sp\n\t" + "stp d0, d1, [sp, #0x10]\n\t" + "stp d2, d3, [sp, #0x20]\n\t" + "stp d4, d5, [sp, #0x30]\n\t" + "stp d6, d7, [sp, #0x40]\n\t" + "stp x0, x1, [sp, #0x50]\n\t" + "stp x2, x3, [sp, #0x60]\n\t" + "stp x4, x5, [sp, #0x70]\n\t" + "stp x6, x7, [sp, #0x80]\n\t" + "ldr x0, [x0]\n\t" /* This->lpVtbl */ + "ldr x0, [x0, #-16]\n\t" /* MIDL_STUBLESS_PROXY_INFO */ + "ldp x1, x4, [x0, #8]\n\t" /* info->ProcFormatString, FormatStringOffset */ + "ldrh w4, [x4, x16, lsl #1]\n\t" /* info->FormatStringOffset[index] */ + "add x1, x1, x4\n\t" /* info->ProcFormatString + offset */ + "ldr x0, [x0]\n\t" /* info->pStubDesc */ + "add x2, sp, #0x50\n\t" /* stack */ + "add x3, sp, #0x10\n\t" /* fpu_stack */ + "bl " __ASM_NAME("ndr_client_call") "\n\t" + "ldp x29, x30, [sp], #0x90\n\t" + "ret" ) + +struct thunk +{ + DWORD ldr_index; /* ldr w16, index */ + DWORD ldr_func; /* ldr x17, func */ + DWORD br; /* br x17 */ + DWORD index; + void *func; +}; + +static inline void init_thunk( struct thunk *thunk, unsigned int index ) +{ + thunk->ldr_index = 0x18000070; /* ldr w16,index */ + thunk->ldr_func = 0x58000071; /* ldr x17,func */ + thunk->br = 0xd61f0220; /* br x17 */ + thunk->index = index; + thunk->func = call_stubless_func; +} + #else /* __i386__ */
#warning You must implement stubless proxies for your CPU diff --git a/dlls/rpcrt4/cstub.c b/dlls/rpcrt4/cstub.c index 607e9d4bc8..1903a5f0c9 100644 --- a/dlls/rpcrt4/cstub.c +++ b/dlls/rpcrt4/cstub.c @@ -183,6 +183,23 @@ typedef struct DWORD offset; } vtbl_method_t;
+#elif defined(__aarch64__) + +static const DWORD opcodes[] = +{ + 0xf9401000, /* ldr x0, [x0,#32] */ + 0xf9400010, /* ldr x16, [x0] */ + 0x18000071, /* ldr w17, offset */ + 0xf8716a10, /* ldr x16, [x16,x17] */ + 0xd61f0200 /* br x16 */ +}; + +typedef struct +{ + DWORD opcodes[ARRAY_SIZE(opcodes)]; + DWORD offset; +} vtbl_method_t; + #else
#warning You must implement delegated proxies/stubs for your CPU diff --git a/dlls/rpcrt4/ndr_stubless.c b/dlls/rpcrt4/ndr_stubless.c index bceecdc827..cc52ee27e8 100644 --- a/dlls/rpcrt4/ndr_stubless.c +++ b/dlls/rpcrt4/ndr_stubless.c @@ -1169,6 +1169,35 @@ __ASM_GLOBAL_FUNC( call_server_func, "5:\tblx r4\n\t" "mov SP, r5\n\t" "pop {r4, r5, PC}" ) +#elif defined __aarch64__ +LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char *args, unsigned int stack_size); +__ASM_GLOBAL_FUNC( call_server_func, + "stp x29, x30, [sp, #-16]!\n\t" + "mov x29, sp\n\t" + "add x3, x2, #15\n\t" + "lsr x3, x3, #4\n\t" + "sub sp, sp, x3, lsl #4\n\t" + "cbz x2, 2f\n" + "1:\tsub x2, x2, #8\n\t" + "ldr x4, [x1, x2]\n\t" + "str x4, [sp, x2]\n\t" + "cbnz x2, 1b\n" + "2:\tmov x8, x0\n\t" + "cbz x3, 3f\n\t" + "ldp x0, x1, [sp], #16\n\t" + "cmp x3, #1\n\t" + "b.le 3f\n\t" + "ldp x2, x3, [sp], #16\n\t" + "cmp x3, #2\n\t" + "b.le 3f\n\t" + "ldp x4, x5, [sp], #16\n\t" + "cmp x3, #3\n\t" + "b.le 3f\n\t" + "ldp x6, x7, [sp], #16\n" + "3:\tblr x8\n\t" + "mov sp, x29\n\t" + "ldp x29, x30, [sp], #16\n\t" + "ret" ) #else #warning call_server_func not implemented for your architecture LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size)