to start winecfg
Signed-off-by: Timothy Pearson tpearson@raptorengineering.com --- configure | 38 + configure.ac | 9 + dlls/dbghelp/Makefile.in | 1 + dlls/dbghelp/cpu_ppc64.c | 100 +++ dlls/dbghelp/dbghelp.c | 6 +- dlls/kernel32/cpu.c | 3 + dlls/kernel32/module.c | 1 + dlls/kernel32/process.c | 8 +- dlls/kernel32/tests/file.c | 2 + dlls/kernel32/tests/loader.c | 2 + dlls/kernel32/tests/module.c | 2 + dlls/ntdll/Makefile.in | 1 + dlls/ntdll/loader.c | 10 +- dlls/ntdll/nt.c | 8 + dlls/ntdll/ntdll.spec | 2 +- dlls/ntdll/process.c | 8 +- dlls/ntdll/server.c | 6 +- dlls/ntdll/signal_powerpc.c | 4 +- dlls/ntdll/signal_ppc64.c | 1221 +++++++++++++++++++++++++++++++ dlls/ntdll/virtual.c | 2 +- dlls/setupapi/fakedll.c | 2 + dlls/ucrtbase/ucrtbase.spec | 2 +- include/basetsd.h | 10 + include/msvcrt/crtdefs.h | 6 + include/rpc.h | 4 +- include/windef.h | 6 + include/wine/server_protocol.h | 6 +- include/winnt.h | 138 +++- libs/port/interlocked.c | 2 +- libs/wine/port.c | 19 + programs/winedbg/Makefile.in | 1 + programs/winedbg/be_ppc.c | 2 +- programs/winedbg/be_ppc64.c | 303 ++++++++ programs/winedbg/gdbproxy.c | 2 + programs/winedbg/tgt_active.c | 2 + programs/winedbg/tgt_minidump.c | 3 + programs/winedbg/winedbg.c | 4 + programs/winetest/main.c | 2 + server/mapping.c | 8 +- server/process.h | 2 +- server/protocol.def | 6 +- server/thread.c | 6 + server/trace.c | 21 + tools/widl/widl.c | 7 + tools/widl/widl.h | 2 +- tools/widl/write_msft.c | 2 +- tools/winebuild/build.h | 4 +- tools/winebuild/import.c | 117 +++ tools/winebuild/main.c | 6 + tools/winebuild/parser.c | 4 +- tools/winebuild/spec32.c | 37 +- tools/winebuild/utils.c | 12 + tools/winedump/minidump.c | 3 + tools/winedump/pe.c | 1 + tools/winegcc/utils.h | 2 +- tools/winegcc/winegcc.c | 41 +- tools/wrc/wrc.c | 3 +- 57 files changed, 2168 insertions(+), 64 deletions(-) create mode 100644 dlls/dbghelp/cpu_ppc64.c create mode 100644 dlls/ntdll/signal_ppc64.c create mode 100644 programs/winedbg/be_ppc64.c
diff --git a/configure b/configure index 793e2ffc5c..c0e210d429 100755 --- a/configure +++ b/configure @@ -5670,6 +5670,15 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext i[3456789]86*) enable_win16=${enable_win16:-yes} ;; + powerpc64*) + CC="$CC -m64" + CXX="$CXX -m64" + host_cpu="powerpc64" + notice_platform="64-bit " + TARGETFLAGS="-m64" + + enable_win64=${enable_win64:-yes} + ;; esac
enable_win16=${enable_win16:-no} @@ -9215,6 +9224,7 @@ fi *x86_64*) exec_prefix='${prefix}/x86_64' ;; *arm*) exec_prefix='${prefix}/armeabi-v7a' ;; *aarch64*) exec_prefix='${prefix}/arm64-v8a' ;; + *powerpc64*) exec_prefix='${prefix}/ppc64' ;; esac fi ;; @@ -16279,6 +16289,34 @@ CFLAGS=$ac_wine_try_cflags_saved fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cflags__fno_omit_frame_pointer" >&5 $as_echo "$ac_cv_cflags__fno_omit_frame_pointer" >&6; } +if test "x$ac_cv_cflags__fno_omit_frame_pointer" = xyes; then : + EXTRACFLAGS="$EXTRACFLAGS -fno-omit-frame-pointer" +fi ;; + esac + + case $host_cpu in + *powerpc64*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports -fno-omit-frame-pointer" >&5 +$as_echo_n "checking whether the compiler supports -fno-omit-frame-pointer... " >&6; } +if ${ac_cv_cflags__fno_omit_frame_pointer+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_wine_try_cflags_saved=$CFLAGS +CFLAGS="$CFLAGS -fno-omit-frame-pointer" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(int argc, char **argv) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_cflags__fno_omit_frame_pointer=yes +else + ac_cv_cflags__fno_omit_frame_pointer=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +CFLAGS=$ac_wine_try_cflags_saved +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cflags__fno_omit_frame_pointer" >&5 +$as_echo "$ac_cv_cflags__fno_omit_frame_pointer" >&6; } if test "x$ac_cv_cflags__fno_omit_frame_pointer" = xyes; then : EXTRACFLAGS="$EXTRACFLAGS -fno-omit-frame-pointer" fi ;; diff --git a/configure.ac b/configure.ac index c978477a51..a615e4a5e6 100644 --- a/configure.ac +++ b/configure.ac @@ -217,6 +217,14 @@ case $host in i[[3456789]]86*) enable_win16=${enable_win16:-yes} ;; + powerpc64*) + CC="$CC -m64" + CXX="$CXX -m64" + host_cpu="powerpc64" + notice_platform="64-bit " + AC_SUBST(TARGETFLAGS,"-m64") + enable_win64=${enable_win64:-yes} + ;; esac
dnl enable_win16 defaults to yes on x86, to no on other CPUs @@ -932,6 +940,7 @@ case $host_os in *x86_64*) exec_prefix='${prefix}/x86_64' ;; *arm*) exec_prefix='${prefix}/armeabi-v7a' ;; *aarch64*) exec_prefix='${prefix}/arm64-v8a' ;; + *powerpc64*) exec_prefix='${prefix}/ppc64' ;; esac fi ;; diff --git a/dlls/dbghelp/Makefile.in b/dlls/dbghelp/Makefile.in index 3e120e8afe..35b14ad6bd 100644 --- a/dlls/dbghelp/Makefile.in +++ b/dlls/dbghelp/Makefile.in @@ -10,6 +10,7 @@ C_SRCS = \ cpu_arm64.c \ cpu_i386.c \ cpu_ppc.c \ + cpu_ppc64.c \ cpu_x86_64.c \ crc32.c \ dbghelp.c \ diff --git a/dlls/dbghelp/cpu_ppc64.c b/dlls/dbghelp/cpu_ppc64.c new file mode 100644 index 0000000000..270da05f39 --- /dev/null +++ b/dlls/dbghelp/cpu_ppc64.c @@ -0,0 +1,100 @@ +/* + * File cpu_ppc64.c + * + * Copyright (C) 2009-2009, Eric Pouech. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <assert.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "dbghelp_private.h" +#include "winternl.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); + +static BOOL ppc64_get_addr(HANDLE hThread, const CONTEXT* ctx, + enum cpu_addr ca, ADDRESS64* addr) +{ + switch (ca) + { +#if defined(__powerpc64__) + case cpu_addr_pc: + addr->Mode = AddrModeFlat; + addr->Segment = 0; /* don't need segment */ + addr->Offset = ctx->Iar; + return TRUE; +#endif + default: + case cpu_addr_stack: + case cpu_addr_frame: + FIXME("not done\n"); + } + return FALSE; +} + +static BOOL ppc64_stack_walk(struct cpu_stack_walk* csw, STACKFRAME64 *frame, + union ctx *ctx) +{ + FIXME("not done\n"); + return FALSE; +} + +static unsigned ppc64_map_dwarf_register(unsigned regno, BOOL eh_frame) +{ + FIXME("not done\n"); + return 0; +} + +static void *ppc64_fetch_context_reg(union ctx *ctx, unsigned regno, unsigned *size) +{ + FIXME("NIY\n"); + return NULL; +} + +static const char* ppc64_fetch_regname(unsigned regno) +{ + FIXME("Unknown register %x\n", regno); + return NULL; +} + +static BOOL ppc64_fetch_minidump_thread(struct dump_context* dc, unsigned index, unsigned flags, const CONTEXT* ctx) +{ + FIXME("NIY\n"); + return FALSE; +} + +static BOOL ppc64_fetch_minidump_module(struct dump_context* dc, unsigned index, unsigned flags) +{ + FIXME("NIY\n"); + return FALSE; +} + +DECLSPEC_HIDDEN struct cpu cpu_ppc64 = { + IMAGE_FILE_MACHINE_POWERPC64, + 8, + CV_REG_NONE, /* FIXME */ + ppc64_get_addr, + ppc64_stack_walk, + NULL, + ppc64_map_dwarf_register, + ppc64_fetch_context_reg, + ppc64_fetch_regname, + ppc64_fetch_minidump_thread, + ppc64_fetch_minidump_module, +}; diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c index ed4d5f4321..e4a0a6d509 100644 --- a/dlls/dbghelp/dbghelp.c +++ b/dlls/dbghelp/dbghelp.c @@ -132,14 +132,16 @@ const char* wine_dbgstr_addr(const ADDRESS64* addr) } }
-extern struct cpu cpu_i386, cpu_x86_64, cpu_ppc, cpu_arm, cpu_arm64; +extern struct cpu cpu_i386, cpu_x86_64, cpu_ppc, cpu_arm, cpu_arm64, cpu_ppc64;
-static struct cpu* dbghelp_cpus[] = {&cpu_i386, &cpu_x86_64, &cpu_ppc, &cpu_arm, &cpu_arm64, NULL}; +static struct cpu* dbghelp_cpus[] = {&cpu_i386, &cpu_x86_64, &cpu_ppc, &cpu_arm, &cpu_arm64, &cpu_ppc64, NULL}; struct cpu* dbghelp_current_cpu = #if defined(__i386__) &cpu_i386 #elif defined(__x86_64__) &cpu_x86_64 +#elif defined(__powerpc64__) + &cpu_ppc64 #elif defined(__powerpc__) &cpu_ppc #elif defined(__arm__) diff --git a/dlls/kernel32/cpu.c b/dlls/kernel32/cpu.c index 9445d0bc05..71032c4ae4 100644 --- a/dlls/kernel32/cpu.c +++ b/dlls/kernel32/cpu.c @@ -145,6 +145,9 @@ VOID WINAPI GetSystemInfo( default: si->dwProcessorType = 0; } break; + case PROCESSOR_ARCHITECTURE_PPC64: + si->dwProcessorType = PROCESSOR_PPC64_OP; + break; case PROCESSOR_ARCHITECTURE_AMD64: si->dwProcessorType = PROCESSOR_AMD_X8664; break; diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c index eb0471cc8e..c70b9ace57 100644 --- a/dlls/kernel32/module.c +++ b/dlls/kernel32/module.c @@ -333,6 +333,7 @@ BOOL WINAPI GetBinaryTypeW( LPCWSTR name, LPDWORD type ) return TRUE; case IMAGE_FILE_MACHINE_AMD64: case IMAGE_FILE_MACHINE_ARM64: + case IMAGE_FILE_MACHINE_POWERPC64: *type = SCS_64BIT_BINARY; return TRUE; } diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index ad257a054e..61c18c77c5 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -111,7 +111,7 @@ static WCHAR winevdm[] = {'C',':','\','w','i','n','d','o','w','s', '\','s','y','s','t','e','m','3','2', '\','w','i','n','e','v','d','m','.','e','x','e',0};
-static const char * const cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64" }; +static const char * const cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64","PowerPC 64" };
static void exec_process( LPCWSTR name );
@@ -173,7 +173,7 @@ static inline unsigned int is_path_prefix( const WCHAR *prefix, const WCHAR *fil */ static inline BOOL is_64bit_arch( cpu_type_t cpu ) { - return (cpu == CPU_x86_64 || cpu == CPU_ARM64); + return (cpu == CPU_x86_64 || cpu == CPU_ARM64 || cpu == CPU_POWERPC64); }
@@ -286,6 +286,7 @@ static enum binary_type get_binary_info( HANDLE hfile, pe_image_info_t *info ) { case 3: info->cpu = CPU_x86; break; case 20: info->cpu = CPU_POWERPC; break; + case 22: info->cpu = CPU_POWERPC64; break; case 40: info->cpu = CPU_ARM; break; case 62: info->cpu = CPU_x86_64; break; case 183: info->cpu = CPU_ARM64; break; @@ -338,6 +339,7 @@ static enum binary_type get_binary_info( HANDLE hfile, pe_image_info_t *info ) case 0x0000000c: info->cpu = CPU_ARM; break; case 0x0100000c: info->cpu = CPU_ARM64; break; case 0x00000012: info->cpu = CPU_POWERPC; break; + case 0x00000014: info->cpu = CPU_POWERPC64; break; } switch(header.macho.filetype) { @@ -2716,6 +2718,8 @@ BOOL WINAPI CreateProcessInternalW( HANDLE token, LPCWSTR app_name, LPWSTR cmd_l /* assume current arch */ #if defined(__i386__) || defined(__x86_64__) pe_info.cpu = is_64bit ? CPU_x86_64 : CPU_x86; +#elif defined(__powerpc64__) + pe_info.cpu = CPU_POWERPC64; #elif defined(__powerpc__) pe_info.cpu = CPU_POWERPC; #elif defined(__arm__) diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 33b17aa327..ef91548c9b 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -2278,6 +2278,8 @@ static BOOL create_fake_dll( LPCSTR filename ) nt->FileHeader.Machine = IMAGE_FILE_MACHINE_I386; #elif defined __x86_64__ nt->FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64; +#elif defined __powerpc64__ + nt->FileHeader.Machine = IMAGE_FILE_MACHINE_POWERPC64; #elif defined __powerpc__ nt->FileHeader.Machine = IMAGE_FILE_MACHINE_POWERPC; #elif defined __arm__ diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index b8dc72bc7f..b2c65c4123 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -102,6 +102,8 @@ static const IMAGE_NT_HEADERS nt_header_template = IMAGE_FILE_MACHINE_I386, /* Machine */ #elif defined __x86_64__ IMAGE_FILE_MACHINE_AMD64, /* Machine */ +#elif defined __powerpc64__ + IMAGE_FILE_MACHINE_POWERPC64, /* Machine */ #elif defined __powerpc__ IMAGE_FILE_MACHINE_POWERPC, /* Machine */ #elif defined __arm__ diff --git a/dlls/kernel32/tests/module.c b/dlls/kernel32/tests/module.c index 3e077f38a9..aba228ff05 100644 --- a/dlls/kernel32/tests/module.c +++ b/dlls/kernel32/tests/module.c @@ -60,6 +60,8 @@ static const struct IMAGE_FILE_MACHINE_I386, /* Machine */ #elif defined __x86_64__ IMAGE_FILE_MACHINE_AMD64, /* Machine */ +#elif defined __powerpc64__ + IMAGE_FILE_MACHINE_POWERPC64, /* Machine */ #elif defined __powerpc__ IMAGE_FILE_MACHINE_POWERPC, /* Machine */ #elif defined __arm__ diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index ed4bb94e4d..fac244546d 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -41,6 +41,7 @@ C_SRCS = \ signal_arm64.c \ signal_i386.c \ signal_powerpc.c \ + signal_ppc64.c \ signal_x86_64.c \ string.c \ sync.c \ diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index d7dbe573a4..6f5e4da929 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -211,7 +211,7 @@ static inline BOOL call_dll_entry_point( DLLENTRYPROC proc, void *module, #endif /* __i386__ */
-#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) +#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__powerpc64__) /************************************************************************* * stub_entry_point * @@ -1964,11 +1964,15 @@ static BOOL is_valid_binary( HMODULE module, const pe_image_info_t *info ) return info->machine == IMAGE_FILE_MACHINE_ARM || info->machine == IMAGE_FILE_MACHINE_THUMB || info->machine == IMAGE_FILE_MACHINE_ARMNT; +#elif defined(__powerpc__) && !defined(__powerpc64__) + return info->machine == IMAGE_FILE_MACHINE_POWERPC; #elif defined(_WIN64) /* support 32-bit IL-only images on 64-bit */ -#ifdef __x86_64__ +#if defined(__x86_64__) if (info->machine == IMAGE_FILE_MACHINE_AMD64) return TRUE; -#else +#elif defined(__aarch64__) if (info->machine == IMAGE_FILE_MACHINE_ARM64) return TRUE; +#elif defined(__powerpc64__) + if (info->machine == IMAGE_FILE_MACHINE_POWERPC64) return TRUE; #endif if (!info->contains_code) return TRUE; if (!(info->image_flags & IMAGE_FLAGS_ComPlusNativeReady)) diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index 0a599470c9..792c7f06e1 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -1136,6 +1136,14 @@ static inline void get_cpuinfo(SYSTEM_CPU_INFORMATION* info) } }
+#elif defined(__powerpc64__) + +static inline void get_cpuinfo(SYSTEM_CPU_INFORMATION* info) +{ + FIXME("CPU Feature detection not implemented.\n"); + info->Architecture = PROCESSOR_ARCHITECTURE_PPC64; +} + #elif defined(__powerpc__) || defined(__ppc__)
static inline void get_cpuinfo(SYSTEM_CPU_INFORMATION* info) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 649774f48a..750eb4e0cb 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -160,7 +160,7 @@ @ stdcall NtCreateTimer(ptr long ptr long) @ stub NtCreateToken # @ stub NtCreateWaitablePort -@ stdcall -arch=win32,arm64 NtCurrentTeb() +@ stdcall -arch=win32,arm64,powerpc64 NtCurrentTeb() # @ stub NtDebugActiveProcess # @ stub NtDebugContinue @ stdcall NtDelayExecution(long ptr) diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c index 2ff8610cce..b1a48d0c1a 100644 --- a/dlls/ntdll/process.c +++ b/dlls/ntdll/process.c @@ -60,11 +60,11 @@ static ULONG execute_flags = MEM_EXECUTE_OPTION_DISABLE;
static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
-static const char * const cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64" }; +static const char * const cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64", "PowerPC 64" };
static inline BOOL is_64bit_arch( cpu_type_t cpu ) { - return (cpu == CPU_x86_64 || cpu == CPU_ARM64); + return (cpu == CPU_x86_64 || cpu == CPU_ARM64 || cpu == CPU_POWERPC64); }
/* @@ -520,13 +520,13 @@ NTSTATUS WINAPI NtQueryInformationProcess( ULONG_PTR val = 0;
if (ProcessHandle == GetCurrentProcess()) val = is_wow64; - else if (server_cpus & ((1 << CPU_x86_64) | (1 << CPU_ARM64))) + else if (server_cpus & ((1 << CPU_x86_64) | (1 << CPU_ARM64) | (1 << CPU_POWERPC64))) { SERVER_START_REQ( get_process_info ) { req->handle = wine_server_obj_handle( ProcessHandle ); if (!(ret = wine_server_call( req ))) - val = (reply->cpu != CPU_x86_64 && reply->cpu != CPU_ARM64); + val = (reply->cpu != CPU_x86_64 && reply->cpu != CPU_ARM64 && reply->cpu != CPU_POWERPC64); } SERVER_END_REQ; } diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index 094b530950..3039acb0e0 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -100,6 +100,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(server); static const enum cpu_type client_cpu = CPU_x86; #elif defined(__x86_64__) static const enum cpu_type client_cpu = CPU_x86_64; +#elif defined(__powerpc64__) +static const enum cpu_type client_cpu = CPU_POWERPC64; #elif defined(__powerpc__) static const enum cpu_type client_cpu = CPU_POWERPC; #elif defined(__arm__) @@ -1475,7 +1477,7 @@ void server_init_process_done(void) */ size_t server_init_thread( void *entry_point, BOOL *suspend ) { - static const char *cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64" }; + static const char *cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64", "PowerPC64" }; static const BOOL is_win64 = (sizeof(void *) > sizeof(int)); const char *arch = getenv( "WINEARCH" ); int ret; @@ -1518,7 +1520,7 @@ size_t server_init_thread( void *entry_point, BOOL *suspend ) } SERVER_END_REQ;
- is_wow64 = !is_win64 && (server_cpus & ((1 << CPU_x86_64) | (1 << CPU_ARM64))) != 0; + is_wow64 = !is_win64 && (server_cpus & ((1 << CPU_x86_64) | (1 << CPU_ARM64) | (1 << CPU_POWERPC64))) != 0; ntdll_get_thread_data()->wow64_redir = is_wow64;
switch (ret) diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c index 86398d8f54..29114be0ff 100644 --- a/dlls/ntdll/signal_powerpc.c +++ b/dlls/ntdll/signal_powerpc.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#ifdef __powerpc__ +#if defined(__powerpc__) && !defined(__powerpc64__)
#include "config.h" #include "wine/port.h" @@ -1267,4 +1267,4 @@ TEB * WINAPI NtCurrentTeb(void) return pthread_getspecific( teb_key ); }
-#endif /* __powerpc__ */ +#endif /* defined(__powerpc__) && !defined(__powerpc64__) */ diff --git a/dlls/ntdll/signal_ppc64.c b/dlls/ntdll/signal_ppc64.c new file mode 100644 index 0000000000..345b15d83e --- /dev/null +++ b/dlls/ntdll/signal_ppc64.c @@ -0,0 +1,1221 @@ +/* + * PowerPC signal handling routines + * + * Copyright 2002 Marcus Meissner, SuSE Linux AG + * Copyright 2019 Timothy Pearson tpearson@raptorengineering.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef __powerpc64__ + +#include "config.h" +#include "wine/port.h" + +#include <assert.h> +#include <signal.h> +#include <stdlib.h> +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +#endif +#ifdef HAVE_SYSCALL_H +# include <syscall.h> +#else +# ifdef HAVE_SYS_SYSCALL_H +# include <sys/syscall.h> +# endif +#endif +#ifdef HAVE_SYS_SIGNAL_H +# include <sys/signal.h> +#endif +#ifdef HAVE_SYS_UCONTEXT_H +# include <sys/ucontext.h> +#endif + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winternl.h" +#include "wine/library.h" +#include "wine/exception.h" +#include "ntdll_misc.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(seh); +WINE_DECLARE_DEBUG_CHANNEL(relay); + +static pthread_key_t teb_key; + +/*********************************************************************** + * signal context platform-specific definitions + */ +#ifdef linux + +/* All Registers access - only for local access */ +# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name) + + +/* Gpr Registers access */ +# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context) + +# define IAR_sig(context) REG_sig(nip, context) /* Program counter */ +# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */ +# define CTR_sig(context) REG_sig(ctr, context) /* Count register */ + +# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */ +# define LR_sig(context) REG_sig(link, context) /* Link register */ +# define CR_sig(context) REG_sig(ccr, context) /* Condition register */ + +/* Float Registers access */ +# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num]) + +# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4))) + +/* Exception Registers access */ +# define DAR_sig(context) REG_sig(dar, context) +# define DSISR_sig(context) REG_sig(dsisr, context) +# define TRAP_sig(context) REG_sig(trap, context) + +#endif /* linux */ + +typedef int (*wine_signal_handler)(unsigned int sig); + +static wine_signal_handler handlers[256]; + +/*********************************************************************** + * dispatch_signal + */ +static inline int dispatch_signal(unsigned int sig) +{ + if (handlers[sig] == NULL) return 0; + return handlers[sig](sig); +} + +/*********************************************************************** + * save_context + * + * Set the register values from a sigcontext. + */ +static void save_context( CONTEXT *context, const ucontext_t *sigcontext ) +{ + +#define C(x) context->Gpr##x = GPR_sig(x,sigcontext) + /* Save Gpr registers */ + C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); + C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20); + C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30); + C(31); +#undef C + + context->Iar = IAR_sig(sigcontext); /* Program Counter */ + context->Msr = MSR_sig(sigcontext); /* Machine State Register (Supervisor) */ + context->Ctr = CTR_sig(sigcontext); + + context->Xer = XER_sig(sigcontext); + context->Lr = LR_sig(sigcontext); + context->Cr = CR_sig(sigcontext); + + /* Saving Exception regs */ + context->Dar = DAR_sig(sigcontext); + context->Dsisr = DSISR_sig(sigcontext); + context->Trap = TRAP_sig(sigcontext); +} + + +/*********************************************************************** + * restore_context + * + * Build a sigcontext from the register values. + */ +static void restore_context( const CONTEXT *context, ucontext_t *sigcontext ) +{ + +#define C(x) GPR_sig(x,sigcontext) = context->Gpr##x + C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); + C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20); + C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30); + C(31); +#undef C + + IAR_sig(sigcontext) = context->Iar; /* Program Counter */ + MSR_sig(sigcontext) = context->Msr; /* Machine State Register (Supervisor) */ + CTR_sig(sigcontext) = context->Ctr; + + XER_sig(sigcontext) = context->Xer; + LR_sig(sigcontext) = context->Lr; + CR_sig(sigcontext) = context->Cr; + + /* Setting Exception regs */ + DAR_sig(sigcontext) = context->Dar; + DSISR_sig(sigcontext) = context->Dsisr; + TRAP_sig(sigcontext) = context->Trap; +} + + +/*********************************************************************** + * save_fpu + * + * Set the FPU context from a sigcontext. + */ +static inline void save_fpu( CONTEXT *context, const ucontext_t *sigcontext ) +{ +#define C(x) context->Fpr##x = FLOAT_sig(x,sigcontext) + C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); + C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20); + C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30); + C(31); +#undef C + context->Fpscr = FPSCR_sig(sigcontext); +} + + +/*********************************************************************** + * restore_fpu + * + * Restore the FPU context to a sigcontext. + */ +static inline void restore_fpu( CONTEXT *context, const ucontext_t *sigcontext ) +{ +#define C(x) FLOAT_sig(x,sigcontext) = context->Fpr##x + C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); + C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20); + C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30); + C(31); +#undef C + FPSCR_sig(sigcontext) = context->Fpscr; +} + + +/*********************************************************************** + * RtlCaptureContext (NTDLL.@) + */ +void WINAPI RtlCaptureContext( CONTEXT *context ) +{ + FIXME("not implemented\n"); + memset( context, 0, sizeof(*context) ); +} + + +/*********************************************************************** + * set_cpu_context + * + * Set the new CPU context. + */ +static void set_cpu_context( const CONTEXT *context ) +{ + FIXME("not implemented\n"); +} + + +/*********************************************************************** + * get_server_context_flags + * + * Convert CPU-specific flags to generic server flags + */ +static unsigned int get_server_context_flags( DWORD flags ) +{ + unsigned int ret = 0; + + if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; + if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; + if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; + if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; + return ret; +} + + +/*********************************************************************** + * copy_context + * + * Copy a register context according to the flags. + */ +static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags ) +{ + if (flags & CONTEXT_CONTROL) + { + to->Msr = from->Msr; + to->Ctr = from->Ctr; + to->Iar = from->Iar; + to->Lr = from->Lr; + to->Dar = from->Dar; + to->Dsisr = from->Dsisr; + to->Trap = from->Trap; + } + if (flags & CONTEXT_INTEGER) + { + to->Gpr0 = from->Gpr0; + to->Gpr1 = from->Gpr1; + to->Gpr2 = from->Gpr2; + to->Gpr3 = from->Gpr3; + to->Gpr4 = from->Gpr4; + to->Gpr5 = from->Gpr5; + to->Gpr6 = from->Gpr6; + to->Gpr7 = from->Gpr7; + to->Gpr8 = from->Gpr8; + to->Gpr9 = from->Gpr9; + to->Gpr10 = from->Gpr10; + to->Gpr11 = from->Gpr11; + to->Gpr12 = from->Gpr12; + to->Gpr13 = from->Gpr13; + to->Gpr14 = from->Gpr14; + to->Gpr15 = from->Gpr15; + to->Gpr16 = from->Gpr16; + to->Gpr17 = from->Gpr17; + to->Gpr18 = from->Gpr18; + to->Gpr19 = from->Gpr19; + to->Gpr20 = from->Gpr20; + to->Gpr21 = from->Gpr21; + to->Gpr22 = from->Gpr22; + to->Gpr23 = from->Gpr23; + to->Gpr24 = from->Gpr24; + to->Gpr25 = from->Gpr25; + to->Gpr26 = from->Gpr26; + to->Gpr27 = from->Gpr27; + to->Gpr28 = from->Gpr28; + to->Gpr29 = from->Gpr29; + to->Gpr30 = from->Gpr30; + to->Gpr31 = from->Gpr31; + to->Xer = from->Xer; + to->Cr = from->Cr; + } + if (flags & CONTEXT_FLOATING_POINT) + { + to->Fpr0 = from->Fpr0; + to->Fpr1 = from->Fpr1; + to->Fpr2 = from->Fpr2; + to->Fpr3 = from->Fpr3; + to->Fpr4 = from->Fpr4; + to->Fpr5 = from->Fpr5; + to->Fpr6 = from->Fpr6; + to->Fpr7 = from->Fpr7; + to->Fpr8 = from->Fpr8; + to->Fpr9 = from->Fpr9; + to->Fpr10 = from->Fpr10; + to->Fpr11 = from->Fpr11; + to->Fpr12 = from->Fpr12; + to->Fpr13 = from->Fpr13; + to->Fpr14 = from->Fpr14; + to->Fpr15 = from->Fpr15; + to->Fpr16 = from->Fpr16; + to->Fpr17 = from->Fpr17; + to->Fpr18 = from->Fpr18; + to->Fpr19 = from->Fpr19; + to->Fpr20 = from->Fpr20; + to->Fpr21 = from->Fpr21; + to->Fpr22 = from->Fpr22; + to->Fpr23 = from->Fpr23; + to->Fpr24 = from->Fpr24; + to->Fpr25 = from->Fpr25; + to->Fpr26 = from->Fpr26; + to->Fpr27 = from->Fpr27; + to->Fpr28 = from->Fpr28; + to->Fpr29 = from->Fpr29; + to->Fpr30 = from->Fpr30; + to->Fpr31 = from->Fpr31; + to->Fpscr = from->Fpscr; + } +} + + +/*********************************************************************** + * context_to_server + * + * Convert a register context to the server format. + */ +NTSTATUS context_to_server( context_t *to, const CONTEXT *from ) +{ + DWORD flags = from->ContextFlags; /* no CPU id? */ + + memset( to, 0, sizeof(*to) ); + to->cpu = CPU_POWERPC64; + + if (flags & CONTEXT_CONTROL) + { + to->flags |= SERVER_CTX_CONTROL; + to->ctl.powerpc64_regs.iar = from->Iar; + to->ctl.powerpc64_regs.msr = from->Msr; + to->ctl.powerpc64_regs.ctr = from->Ctr; + to->ctl.powerpc64_regs.lr = from->Lr; + to->ctl.powerpc64_regs.dar = from->Dar; + to->ctl.powerpc64_regs.dsisr = from->Dsisr; + to->ctl.powerpc64_regs.trap = from->Trap; + } + if (flags & CONTEXT_INTEGER) + { + to->flags |= SERVER_CTX_INTEGER; + to->integer.powerpc64_regs.gpr[0] = from->Gpr0; + to->integer.powerpc64_regs.gpr[1] = from->Gpr1; + to->integer.powerpc64_regs.gpr[2] = from->Gpr2; + to->integer.powerpc64_regs.gpr[3] = from->Gpr3; + to->integer.powerpc64_regs.gpr[4] = from->Gpr4; + to->integer.powerpc64_regs.gpr[5] = from->Gpr5; + to->integer.powerpc64_regs.gpr[6] = from->Gpr6; + to->integer.powerpc64_regs.gpr[7] = from->Gpr7; + to->integer.powerpc64_regs.gpr[8] = from->Gpr8; + to->integer.powerpc64_regs.gpr[9] = from->Gpr9; + to->integer.powerpc64_regs.gpr[10] = from->Gpr10; + to->integer.powerpc64_regs.gpr[11] = from->Gpr11; + to->integer.powerpc64_regs.gpr[12] = from->Gpr12; + to->integer.powerpc64_regs.gpr[13] = from->Gpr13; + to->integer.powerpc64_regs.gpr[14] = from->Gpr14; + to->integer.powerpc64_regs.gpr[15] = from->Gpr15; + to->integer.powerpc64_regs.gpr[16] = from->Gpr16; + to->integer.powerpc64_regs.gpr[17] = from->Gpr17; + to->integer.powerpc64_regs.gpr[18] = from->Gpr18; + to->integer.powerpc64_regs.gpr[19] = from->Gpr19; + to->integer.powerpc64_regs.gpr[20] = from->Gpr20; + to->integer.powerpc64_regs.gpr[21] = from->Gpr21; + to->integer.powerpc64_regs.gpr[22] = from->Gpr22; + to->integer.powerpc64_regs.gpr[23] = from->Gpr23; + to->integer.powerpc64_regs.gpr[24] = from->Gpr24; + to->integer.powerpc64_regs.gpr[25] = from->Gpr25; + to->integer.powerpc64_regs.gpr[26] = from->Gpr26; + to->integer.powerpc64_regs.gpr[27] = from->Gpr27; + to->integer.powerpc64_regs.gpr[28] = from->Gpr28; + to->integer.powerpc64_regs.gpr[29] = from->Gpr29; + to->integer.powerpc64_regs.gpr[30] = from->Gpr30; + to->integer.powerpc64_regs.gpr[31] = from->Gpr31; + to->integer.powerpc64_regs.xer = from->Xer; + to->integer.powerpc64_regs.cr = from->Cr; + } + if (flags & CONTEXT_FLOATING_POINT) + { + to->flags |= SERVER_CTX_FLOATING_POINT; + to->fp.powerpc64_regs.fpr[0] = from->Fpr0; + to->fp.powerpc64_regs.fpr[1] = from->Fpr1; + to->fp.powerpc64_regs.fpr[2] = from->Fpr2; + to->fp.powerpc64_regs.fpr[3] = from->Fpr3; + to->fp.powerpc64_regs.fpr[4] = from->Fpr4; + to->fp.powerpc64_regs.fpr[5] = from->Fpr5; + to->fp.powerpc64_regs.fpr[6] = from->Fpr6; + to->fp.powerpc64_regs.fpr[7] = from->Fpr7; + to->fp.powerpc64_regs.fpr[8] = from->Fpr8; + to->fp.powerpc64_regs.fpr[9] = from->Fpr9; + to->fp.powerpc64_regs.fpr[10] = from->Fpr10; + to->fp.powerpc64_regs.fpr[11] = from->Fpr11; + to->fp.powerpc64_regs.fpr[12] = from->Fpr12; + to->fp.powerpc64_regs.fpr[13] = from->Fpr13; + to->fp.powerpc64_regs.fpr[14] = from->Fpr14; + to->fp.powerpc64_regs.fpr[15] = from->Fpr15; + to->fp.powerpc64_regs.fpr[16] = from->Fpr16; + to->fp.powerpc64_regs.fpr[17] = from->Fpr17; + to->fp.powerpc64_regs.fpr[18] = from->Fpr18; + to->fp.powerpc64_regs.fpr[19] = from->Fpr19; + to->fp.powerpc64_regs.fpr[20] = from->Fpr20; + to->fp.powerpc64_regs.fpr[21] = from->Fpr21; + to->fp.powerpc64_regs.fpr[22] = from->Fpr22; + to->fp.powerpc64_regs.fpr[23] = from->Fpr23; + to->fp.powerpc64_regs.fpr[24] = from->Fpr24; + to->fp.powerpc64_regs.fpr[25] = from->Fpr25; + to->fp.powerpc64_regs.fpr[26] = from->Fpr26; + to->fp.powerpc64_regs.fpr[27] = from->Fpr27; + to->fp.powerpc64_regs.fpr[28] = from->Fpr28; + to->fp.powerpc64_regs.fpr[29] = from->Fpr29; + to->fp.powerpc64_regs.fpr[30] = from->Fpr30; + to->fp.powerpc64_regs.fpr[31] = from->Fpr31; + to->fp.powerpc64_regs.fpscr = from->Fpscr; + } + return STATUS_SUCCESS; +} + + +/*********************************************************************** + * context_from_server + * + * Convert a register context from the server format. + */ +NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) +{ + if (from->cpu != CPU_POWERPC64) return STATUS_INVALID_PARAMETER; + + to->ContextFlags = 0; /* no CPU id? */ + if (from->flags & SERVER_CTX_CONTROL) + { + to->ContextFlags |= CONTEXT_CONTROL; + to->Msr = from->ctl.powerpc64_regs.msr; + to->Ctr = from->ctl.powerpc64_regs.ctr; + to->Iar = from->ctl.powerpc64_regs.iar; + to->Lr = from->ctl.powerpc64_regs.lr; + to->Dar = from->ctl.powerpc64_regs.dar; + to->Dsisr = from->ctl.powerpc64_regs.dsisr; + to->Trap = from->ctl.powerpc64_regs.trap; + } + if (from->flags & SERVER_CTX_INTEGER) + { + to->ContextFlags |= CONTEXT_INTEGER; + to->Gpr0 = from->integer.powerpc64_regs.gpr[0]; + to->Gpr1 = from->integer.powerpc64_regs.gpr[1]; + to->Gpr2 = from->integer.powerpc64_regs.gpr[2]; + to->Gpr3 = from->integer.powerpc64_regs.gpr[3]; + to->Gpr4 = from->integer.powerpc64_regs.gpr[4]; + to->Gpr5 = from->integer.powerpc64_regs.gpr[5]; + to->Gpr6 = from->integer.powerpc64_regs.gpr[6]; + to->Gpr7 = from->integer.powerpc64_regs.gpr[7]; + to->Gpr8 = from->integer.powerpc64_regs.gpr[8]; + to->Gpr9 = from->integer.powerpc64_regs.gpr[9]; + to->Gpr10 = from->integer.powerpc64_regs.gpr[10]; + to->Gpr11 = from->integer.powerpc64_regs.gpr[11]; + to->Gpr12 = from->integer.powerpc64_regs.gpr[12]; + to->Gpr13 = from->integer.powerpc64_regs.gpr[13]; + to->Gpr14 = from->integer.powerpc64_regs.gpr[14]; + to->Gpr15 = from->integer.powerpc64_regs.gpr[15]; + to->Gpr16 = from->integer.powerpc64_regs.gpr[16]; + to->Gpr17 = from->integer.powerpc64_regs.gpr[17]; + to->Gpr18 = from->integer.powerpc64_regs.gpr[18]; + to->Gpr19 = from->integer.powerpc64_regs.gpr[19]; + to->Gpr20 = from->integer.powerpc64_regs.gpr[20]; + to->Gpr21 = from->integer.powerpc64_regs.gpr[21]; + to->Gpr22 = from->integer.powerpc64_regs.gpr[22]; + to->Gpr23 = from->integer.powerpc64_regs.gpr[23]; + to->Gpr24 = from->integer.powerpc64_regs.gpr[24]; + to->Gpr25 = from->integer.powerpc64_regs.gpr[25]; + to->Gpr26 = from->integer.powerpc64_regs.gpr[26]; + to->Gpr27 = from->integer.powerpc64_regs.gpr[27]; + to->Gpr28 = from->integer.powerpc64_regs.gpr[28]; + to->Gpr29 = from->integer.powerpc64_regs.gpr[29]; + to->Gpr30 = from->integer.powerpc64_regs.gpr[30]; + to->Gpr31 = from->integer.powerpc64_regs.gpr[31]; + to->Xer = from->integer.powerpc64_regs.xer; + to->Cr = from->integer.powerpc64_regs.cr; + } + if (from->flags & SERVER_CTX_FLOATING_POINT) + { + to->ContextFlags |= CONTEXT_FLOATING_POINT; + to->Fpr0 = from->fp.powerpc64_regs.fpr[0]; + to->Fpr1 = from->fp.powerpc64_regs.fpr[1]; + to->Fpr2 = from->fp.powerpc64_regs.fpr[2]; + to->Fpr3 = from->fp.powerpc64_regs.fpr[3]; + to->Fpr4 = from->fp.powerpc64_regs.fpr[4]; + to->Fpr5 = from->fp.powerpc64_regs.fpr[5]; + to->Fpr6 = from->fp.powerpc64_regs.fpr[6]; + to->Fpr7 = from->fp.powerpc64_regs.fpr[7]; + to->Fpr8 = from->fp.powerpc64_regs.fpr[8]; + to->Fpr9 = from->fp.powerpc64_regs.fpr[9]; + to->Fpr10 = from->fp.powerpc64_regs.fpr[10]; + to->Fpr11 = from->fp.powerpc64_regs.fpr[11]; + to->Fpr12 = from->fp.powerpc64_regs.fpr[12]; + to->Fpr13 = from->fp.powerpc64_regs.fpr[13]; + to->Fpr14 = from->fp.powerpc64_regs.fpr[14]; + to->Fpr15 = from->fp.powerpc64_regs.fpr[15]; + to->Fpr16 = from->fp.powerpc64_regs.fpr[16]; + to->Fpr17 = from->fp.powerpc64_regs.fpr[17]; + to->Fpr18 = from->fp.powerpc64_regs.fpr[18]; + to->Fpr19 = from->fp.powerpc64_regs.fpr[19]; + to->Fpr20 = from->fp.powerpc64_regs.fpr[20]; + to->Fpr21 = from->fp.powerpc64_regs.fpr[21]; + to->Fpr22 = from->fp.powerpc64_regs.fpr[22]; + to->Fpr23 = from->fp.powerpc64_regs.fpr[23]; + to->Fpr24 = from->fp.powerpc64_regs.fpr[24]; + to->Fpr25 = from->fp.powerpc64_regs.fpr[25]; + to->Fpr26 = from->fp.powerpc64_regs.fpr[26]; + to->Fpr27 = from->fp.powerpc64_regs.fpr[27]; + to->Fpr28 = from->fp.powerpc64_regs.fpr[28]; + to->Fpr29 = from->fp.powerpc64_regs.fpr[29]; + to->Fpr30 = from->fp.powerpc64_regs.fpr[30]; + to->Fpr31 = from->fp.powerpc64_regs.fpr[31]; + to->Fpscr = from->fp.powerpc64_regs.fpscr; + } + return STATUS_SUCCESS; +} + + +/*********************************************************************** + * NtSetContextThread (NTDLL.@) + * ZwSetContextThread (NTDLL.@) + */ +NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) +{ + NTSTATUS ret; + BOOL self; + context_t server_context; + + context_to_server( &server_context, context ); + ret = set_thread_context( handle, &server_context, &self ); + if (self && ret == STATUS_SUCCESS) set_cpu_context( context ); + return ret; +} + + +/*********************************************************************** + * NtGetContextThread (NTDLL.@) + * ZwGetContextThread (NTDLL.@) + */ +NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) +{ + NTSTATUS ret; + DWORD needed_flags = context->ContextFlags; + BOOL self = (handle == GetCurrentThread()); + + if (!self) + { + context_t server_context; + unsigned int server_flags = get_server_context_flags( context->ContextFlags ); + + if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret; + if ((ret = context_from_server( context, &server_context ))) return ret; + needed_flags &= ~context->ContextFlags; + } + + if (self && needed_flags) + { + CONTEXT ctx; + RtlCaptureContext( &ctx ); + copy_context( context, &ctx, ctx.ContextFlags & needed_flags ); + context->ContextFlags |= ctx.ContextFlags & needed_flags; + } + return STATUS_SUCCESS; +} + + +/********************************************************************** + * call_stack_handlers + * + * Call the stack handlers chain. + */ +static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) +{ + EXCEPTION_POINTERS ptrs; + + FIXME( "not implemented on PowerPC 64\n" ); + + /* hack: call unhandled exception filter directly */ + ptrs.ExceptionRecord = rec; + ptrs.ContextRecord = context; + call_unhandled_exception_filter( &ptrs ); + return STATUS_UNHANDLED_EXCEPTION; +} + + +/******************************************************************* + * raise_exception + * + * Implementation of NtRaiseException. + */ +static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance ) +{ + NTSTATUS status; + + if (first_chance) + { + DWORD c; + + TRACE( "code=%x flags=%x addr=%p ip=%llx tid=%04x\n", + rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, + context->Iar, GetCurrentThreadId() ); + for (c = 0; c < rec->NumberParameters; c++) + TRACE( " info[%d]=%08llx\n", c, rec->ExceptionInformation[c] ); + if (rec->ExceptionCode == EXCEPTION_WINE_STUB) + { + if (rec->ExceptionInformation[1] >> 16) + MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n", + rec->ExceptionAddress, + (char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] ); + else + MESSAGE( "wine: Call from %p to unimplemented function %s.%lld, aborting\n", + rec->ExceptionAddress, + (char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] ); + } + else + { + /* FIXME: dump context */ + } + + status = send_debug_event( rec, TRUE, context ); + if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) + return STATUS_SUCCESS; + + if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION) + return STATUS_SUCCESS; + + if ((status = call_stack_handlers( rec, context )) != STATUS_UNHANDLED_EXCEPTION) + return status; + } + + /* last chance exception */ + + status = send_debug_event( rec, FALSE, context ); + if (status != DBG_CONTINUE) + { + if (rec->ExceptionFlags & EH_STACK_INVALID) + ERR("Exception frame is not in stack limits => unable to dispatch exception.\n"); + else if (rec->ExceptionCode == STATUS_NONCONTINUABLE_EXCEPTION) + ERR("Process attempted to continue execution after noncontinuable exception.\n"); + else + ERR("Unhandled exception code %x flags %x addr %p\n", + rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress ); + NtTerminateProcess( NtCurrentProcess(), rec->ExceptionCode ); + } + return STATUS_SUCCESS; +} + + +/********************************************************************** + * segv_handler + * + * Handler for SIGSEGV and related errors. + */ +static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) +{ + EXCEPTION_RECORD rec; + CONTEXT context; + NTSTATUS status; + + save_context( &context, sigcontext ); + + rec.ExceptionRecord = NULL; + rec.ExceptionFlags = EXCEPTION_CONTINUABLE; + rec.ExceptionAddress = (LPVOID)context.Iar; + rec.NumberParameters = 0; + + switch (signal) + { + case SIGSEGV: + switch (siginfo->si_code & 0xffff) + { + case SEGV_MAPERR: + case SEGV_ACCERR: + rec.NumberParameters = 2; + rec.ExceptionInformation[0] = 0; /* FIXME ? */ + rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr; + if (!(rec.ExceptionCode = virtual_handle_fault(siginfo->si_addr, rec.ExceptionInformation[0], FALSE))) + goto done; + break; + default: + FIXME("Unhandled SIGSEGV/%x\n",siginfo->si_code); + break; + } + break; + case SIGBUS: + switch (siginfo->si_code & 0xffff) + { + case BUS_ADRALN: + rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; + break; +#ifdef BUS_ADRERR + case BUS_ADRERR: +#endif +#ifdef BUS_OBJERR + case BUS_OBJERR: + /* FIXME: correct for all cases ? */ + rec.NumberParameters = 2; + rec.ExceptionInformation[0] = 0; /* FIXME ? */ + rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr; + if (!(rec.ExceptionCode = virtual_handle_fault(siginfo->si_addr, rec.ExceptionInformation[0], FALSE))) + goto done; + break; +#endif + default: + FIXME("Unhandled SIGBUS/%x\n",siginfo->si_code); + break; + } + break; + case SIGILL: + switch (siginfo->si_code & 0xffff) + { + case ILL_ILLOPC: /* illegal opcode */ +#ifdef ILL_ILLOPN + case ILL_ILLOPN: /* illegal operand */ +#endif +#ifdef ILL_ILLADR + case ILL_ILLADR: /* illegal addressing mode */ +#endif +#ifdef ILL_ILLTRP + case ILL_ILLTRP: /* illegal trap */ +#endif +#ifdef ILL_COPROC + case ILL_COPROC: /* coprocessor error */ +#endif + rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + break; + case ILL_PRVOPC: /* privileged opcode */ +#ifdef ILL_PRVREG + case ILL_PRVREG: /* privileged register */ +#endif + rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION; + break; +#ifdef ILL_BADSTK + case ILL_BADSTK: /* internal stack error */ + rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW; + break; +#endif + default: + FIXME("Unhandled SIGILL/%x\n", siginfo->si_code); + break; + } + break; + } + status = raise_exception( &rec, &context, TRUE ); + if (status) raise_status( status, &rec ); +done: + restore_context( &context, sigcontext ); +} + +/********************************************************************** + * trap_handler + * + * Handler for SIGTRAP. + */ +static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext ) +{ + EXCEPTION_RECORD rec; + CONTEXT context; + NTSTATUS status; + + save_context( &context, sigcontext ); + + rec.ExceptionFlags = EXCEPTION_CONTINUABLE; + rec.ExceptionRecord = NULL; + rec.ExceptionAddress = (LPVOID)context.Iar; + rec.NumberParameters = 0; + + /* FIXME: check if we might need to modify PC */ + switch (siginfo->si_code & 0xffff) + { +#ifdef TRAP_BRKPT + case TRAP_BRKPT: + rec.ExceptionCode = EXCEPTION_BREAKPOINT; + break; +#endif +#ifdef TRAP_TRACE + case TRAP_TRACE: + rec.ExceptionCode = EXCEPTION_SINGLE_STEP; + break; +#endif + default: + FIXME("Unhandled SIGTRAP/%x\n", siginfo->si_code); + break; + } + status = raise_exception( &rec, &context, TRUE ); + if (status) raise_status( status, &rec ); + restore_context( &context, sigcontext ); +} + +/********************************************************************** + * fpe_handler + * + * Handler for SIGFPE. + */ +static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext ) +{ + EXCEPTION_RECORD rec; + CONTEXT context; + NTSTATUS status; + + save_fpu( &context, sigcontext ); + save_context( &context, sigcontext ); + + switch (siginfo->si_code & 0xffff ) + { +#ifdef FPE_FLTSUB + case FPE_FLTSUB: + rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; + break; +#endif +#ifdef FPE_INTDIV + case FPE_INTDIV: + rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO; + break; +#endif +#ifdef FPE_INTOVF + case FPE_INTOVF: + rec.ExceptionCode = EXCEPTION_INT_OVERFLOW; + break; +#endif +#ifdef FPE_FLTDIV + case FPE_FLTDIV: + rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO; + break; +#endif +#ifdef FPE_FLTOVF + case FPE_FLTOVF: + rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW; + break; +#endif +#ifdef FPE_FLTUND + case FPE_FLTUND: + rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW; + break; +#endif +#ifdef FPE_FLTRES + case FPE_FLTRES: + rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT; + break; +#endif +#ifdef FPE_FLTINV + case FPE_FLTINV: +#endif + default: + rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; + break; + } + rec.ExceptionFlags = EXCEPTION_CONTINUABLE; + rec.ExceptionRecord = NULL; + rec.ExceptionAddress = (LPVOID)context.Iar; + rec.NumberParameters = 0; + status = raise_exception( &rec, &context, TRUE ); + if (status) raise_status( status, &rec ); + + restore_context( &context, sigcontext ); + restore_fpu( &context, sigcontext ); +} + +/********************************************************************** + * int_handler + * + * Handler for SIGINT. + */ +static void int_handler( int signal, siginfo_t *siginfo, void *sigcontext ) +{ + if (!dispatch_signal(SIGINT)) + { + EXCEPTION_RECORD rec; + CONTEXT context; + NTSTATUS status; + + save_context( &context, sigcontext ); + rec.ExceptionCode = CONTROL_C_EXIT; + rec.ExceptionFlags = EXCEPTION_CONTINUABLE; + rec.ExceptionRecord = NULL; + rec.ExceptionAddress = (LPVOID)context.Iar; + rec.NumberParameters = 0; + status = raise_exception( &rec, &context, TRUE ); + if (status) raise_status( status, &rec ); + restore_context( &context, sigcontext ); + } +} + + +/********************************************************************** + * abrt_handler + * + * Handler for SIGABRT. + */ +static void abrt_handler( int signal, siginfo_t *siginfo, void *sigcontext ) +{ + EXCEPTION_RECORD rec; + CONTEXT context; + NTSTATUS status; + + save_context( &context, sigcontext ); + rec.ExceptionCode = EXCEPTION_WINE_ASSERTION; + rec.ExceptionFlags = EH_NONCONTINUABLE; + rec.ExceptionRecord = NULL; + rec.ExceptionAddress = (LPVOID)context.Iar; + rec.NumberParameters = 0; + status = raise_exception( &rec, &context, TRUE ); + if (status) raise_status( status, &rec ); + restore_context( &context, sigcontext ); +} + + +/********************************************************************** + * quit_handler + * + * Handler for SIGQUIT. + */ +static void quit_handler( int signal, siginfo_t *siginfo, void *sigcontext ) +{ + abort_thread(0); +} + + +/********************************************************************** + * usr1_handler + * + * Handler for SIGUSR1, used to signal a thread that it got suspended. + */ +static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext ) +{ + CONTEXT context; + + save_context( &context, sigcontext ); + wait_suspend( &context ); + restore_context( &context, sigcontext ); +} + + +/*********************************************************************** + * __wine_set_signal_handler (NTDLL.@) + */ +int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh) +{ + if (sig >= ARRAY_SIZE(handlers)) return -1; + if (handlers[sig] != NULL) return -2; + handlers[sig] = wsh; + return 0; +} + + +/********************************************************************** + * signal_alloc_thread + */ +NTSTATUS signal_alloc_thread( TEB **teb ) +{ + static size_t sigstack_zero_bits; + SIZE_T size; + NTSTATUS status; + + if (!sigstack_zero_bits) + { + size_t min_size = page_size; /* this is just for the TEB, we don't use a signal stack yet */ + /* find the first power of two not smaller than min_size */ + while ((1u << sigstack_zero_bits) < min_size) sigstack_zero_bits++; + assert( sizeof(TEB) <= min_size ); + } + + size = 1 << sigstack_zero_bits; + *teb = NULL; + if (!(status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)teb, sigstack_zero_bits, + &size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE ))) + { + (*teb)->Tib.Self = &(*teb)->Tib; + (*teb)->Tib.ExceptionList = (void *)~0UL; + } + return status; +} + + +/********************************************************************** + * signal_free_thread + */ +void signal_free_thread( TEB *teb ) +{ + SIZE_T size = 0; + + NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE ); +} + + +/********************************************************************** + * signal_init_thread + */ +void signal_init_thread( TEB *teb ) +{ + static BOOL init_done; + + if (!init_done) + { + pthread_key_create( &teb_key, NULL ); + init_done = TRUE; + } + pthread_setspecific( teb_key, teb ); +} + + +/********************************************************************** + * signal_init_process + */ +void signal_init_process(void) +{ + struct sigaction sig_act; + + sig_act.sa_mask = server_block_set; + sig_act.sa_flags = SA_RESTART | SA_SIGINFO; + + sig_act.sa_sigaction = int_handler; + if (sigaction( SIGINT, &sig_act, NULL ) == -1) goto error; + sig_act.sa_sigaction = fpe_handler; + if (sigaction( SIGFPE, &sig_act, NULL ) == -1) goto error; + sig_act.sa_sigaction = abrt_handler; + if (sigaction( SIGABRT, &sig_act, NULL ) == -1) goto error; + sig_act.sa_sigaction = quit_handler; + if (sigaction( SIGQUIT, &sig_act, NULL ) == -1) goto error; + sig_act.sa_sigaction = usr1_handler; + if (sigaction( SIGUSR1, &sig_act, NULL ) == -1) goto error; + + sig_act.sa_sigaction = segv_handler; + if (sigaction( SIGSEGV, &sig_act, NULL ) == -1) goto error; + if (sigaction( SIGILL, &sig_act, NULL ) == -1) goto error; +#ifdef SIGBUS + if (sigaction( SIGBUS, &sig_act, NULL ) == -1) goto error; +#endif + +#ifdef SIGTRAP + sig_act.sa_sigaction = trap_handler; + if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error; +#endif + return; + + error: + perror("sigaction"); + exit(1); +} + + +/*********************************************************************** + * RtlUnwind (NTDLL.@) + */ +void WINAPI RtlUnwind( PVOID pEndFrame, PVOID targetIp, PEXCEPTION_RECORD pRecord, PVOID retval ) +{ + FIXME( "Not implemented on PowerPC 64\n" ); +} + +/******************************************************************* + * NtRaiseException (NTDLL.@) + */ +NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance ) +{ + NTSTATUS status = raise_exception( rec, context, first_chance ); + if (status == STATUS_SUCCESS) NtSetContextThread( GetCurrentThread(), context ); + return status; +} + +/*********************************************************************** + * RtlRaiseException (NTDLL.@) + */ +void WINAPI RtlRaiseException( EXCEPTION_RECORD *rec ) +{ + CONTEXT context; + NTSTATUS status; + + RtlCaptureContext( &context ); + rec->ExceptionAddress = (void *)context.Iar; + status = raise_exception( rec, &context, TRUE ); + if (status) raise_status( status, rec ); +} + +/************************************************************************* + * RtlCaptureStackBackTrace (NTDLL.@) + */ +USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash ) +{ + FIXME( "(%d, %d, %p, %p) stub!\n", skip, count, buffer, hash ); + return 0; +} + +/*********************************************************************** + * call_thread_entry_point + */ +static void WINAPI call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) +{ + __TRY + { + TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg ); + RtlExitUserThread( entry( arg )); + } + __EXCEPT(call_unhandled_exception_filter) + { + NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); + } + __ENDTRY + abort(); /* should not be reached */ +} + +typedef void (WINAPI *thread_start_func)(LPTHREAD_START_ROUTINE,void *); + +struct startup_info +{ + thread_start_func start; + LPTHREAD_START_ROUTINE entry; + void *arg; + BOOL suspend; +}; + +/*********************************************************************** + * thread_startup + */ +static void thread_startup( void *param ) +{ + CONTEXT context = { 0 }; + struct startup_info *info = param; + + /* build the initial context */ + context.ContextFlags = CONTEXT_FULL; + context.Gpr1 = (DWORD64)NtCurrentTeb()->Tib.StackBase; + context.Gpr3 = (DWORD64)info->entry; + context.Gpr4 = (DWORD64)info->arg; + context.Iar = (DWORD64)info->start; + + if (info->suspend) wait_suspend( &context ); + LdrInitializeThunk( &context, (void **)&context.Gpr3, 0, 0 ); + + ((thread_start_func)context.Iar)( (LPTHREAD_START_ROUTINE)context.Gpr3, (void *)context.Gpr4 ); +} + +/*********************************************************************** + * signal_start_thread + * + * Thread startup sequence: + * signal_start_thread() + * -> thread_startup() + * -> call_thread_entry_point() + */ +void signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend ) +{ + struct startup_info info = { call_thread_entry_point, entry, arg, suspend }; + wine_switch_to_stack( thread_startup, &info, NtCurrentTeb()->Tib.StackBase ); +} + +/********************************************************************** + * signal_start_process + * + * Process startup sequence: + * signal_start_process() + * -> thread_startup() + * -> kernel32_start_process() + */ +void signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) +{ + struct startup_info info = { kernel32_start_process, entry, NtCurrentTeb()->Peb, suspend }; + wine_switch_to_stack( thread_startup, &info, NtCurrentTeb()->Tib.StackBase ); +} + +/*********************************************************************** + * signal_exit_thread + */ +void signal_exit_thread( int status ) +{ + exit_thread( status ); +} + +/*********************************************************************** + * signal_exit_process + */ +void signal_exit_process( int status ) +{ + exit( status ); +} + +/********************************************************************** + * DbgBreakPoint (NTDLL.@) + */ +void WINAPI DbgBreakPoint(void) +{ + kill(getpid(), SIGTRAP); +} + +/********************************************************************** + * DbgUserBreakPoint (NTDLL.@) + */ +void WINAPI DbgUserBreakPoint(void) +{ + kill(getpid(), SIGTRAP); +} + +/********************************************************************** + * NtCurrentTeb (NTDLL.@) + */ +TEB * WINAPI NtCurrentTeb(void) +{ + return pthread_getspecific( teb_key ); +} + +#endif /* __powerpc64__ */ diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 76dc6c284d..6788bb137f 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -3208,7 +3208,7 @@ void virtual_fill_image_information( const pe_image_info_t *pe_info, SECTION_IMA info->ImageFileSize = pe_info->file_size; info->CheckSum = pe_info->checksum; #ifndef _WIN64 /* don't return 64-bit values to 32-bit processes */ - if (pe_info->machine == IMAGE_FILE_MACHINE_AMD64 || pe_info->machine == IMAGE_FILE_MACHINE_ARM64) + if (pe_info->machine == IMAGE_FILE_MACHINE_AMD64 || pe_info->machine == IMAGE_FILE_MACHINE_ARM64 || pe_info->machine == IMAGE_FILE_MACHINE_POWERPC64) { info->TransferAddress = (void *)0x81231234; /* sic */ info->MaximumStackSize = 0x100000; diff --git a/dlls/setupapi/fakedll.c b/dlls/setupapi/fakedll.c index e0d012a034..8c68a50346 100644 --- a/dlls/setupapi/fakedll.c +++ b/dlls/setupapi/fakedll.c @@ -280,6 +280,8 @@ static BOOL build_fake_dll( HANDLE file, const WCHAR *name ) nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARM64; #elif defined __arm__ nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARMNT; +#elif defined __powerpc64__ + nt->FileHeader.Machine = IMAGE_FILE_MACHINE_POWERPC64; #elif defined __powerpc__ nt->FileHeader.Machine = IMAGE_FILE_MACHINE_POWERPC; #else diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 00c806483e..6219ef265e 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -1324,7 +1324,7 @@ @ stub _o__scalbf @ stub _o__searchenv @ stub _o__searchenv_s -@ cdecl _o__seh_filter_dll(long ptr) __CppXcptFilter +@ cdecl -arch=i386,x86_64,arm,arm64 _o__seh_filter_dll(long ptr) __CppXcptFilter @ cdecl _o__seh_filter_exe(long ptr) _XcptFilter @ stub _o__set_abort_behavior @ cdecl _o__set_app_type(long) MSVCRT___set_app_type diff --git a/include/basetsd.h b/include/basetsd.h index 96ea3f01bc..4972f549b5 100644 --- a/include/basetsd.h +++ b/include/basetsd.h @@ -277,6 +277,16 @@ typedef ULONG_PTR KAFFINITY, *PKAFFINITY; # undef WORDS_BIGENDIAN # undef BITFIELDS_BIGENDIAN # define ALLOW_UNALIGNED_ACCESS +#elif defined(__powerpc64__) +# if defined(__BIG_ENDIAN__) +# define WORDS_BIGENDIAN +# define BITFIELDS_BIGENDIAN +# undef ALLOW_UNALIGNED_ACCESS +# else +# undef WORDS_BIGENDIAN +# undef BITFIELDS_BIGENDIAN +# undef ALLOW_UNALIGNED_ACCESS +#endif #elif defined(__powerpc__) # define WORDS_BIGENDIAN # define BITFIELDS_BIGENDIAN diff --git a/include/msvcrt/crtdefs.h b/include/msvcrt/crtdefs.h index 0c0b08748e..cfc0122719 100644 --- a/include/msvcrt/crtdefs.h +++ b/include/msvcrt/crtdefs.h @@ -64,6 +64,9 @@ # define __stdcall __attribute__((pcs("aapcs-vfp"))) # elif defined(__aarch64__) && defined (__GNUC__) # define __stdcall __attribute__((ms_abi)) +# elif defined(__powerpc64__) && defined (__GNUC__) + /* ppc64 relies on long calls being generated for thunks (r2 save / restore) */ +# define __stdcall __attribute__((__longcall__)) # else /* __i386__ */ # define __stdcall # endif /* __i386__ */ @@ -86,6 +89,9 @@ # define __cdecl __attribute__((pcs("aapcs-vfp"))) # elif defined(__aarch64__) && defined (__GNUC__) # define __cdecl __attribute__((ms_abi)) +# elif defined(__powerpc64__) && defined (__GNUC__) + /* ppc64 relies on long calls being generated for thunks (r2 save / restore) */ +# define __cdecl __attribute__((__longcall__)) # elif !defined(_MSC_VER) # define __cdecl # endif diff --git a/include/rpc.h b/include/rpc.h index eb7d0417bd..56b1112418 100644 --- a/include/rpc.h +++ b/include/rpc.h @@ -25,7 +25,9 @@ #ifndef __WINE_RPC_H #define __WINE_RPC_H
-#if defined(__powerpc__) || defined(_MAC) /* ? */ +#if defined(__powerpc64__) +# define __RPC_WIN64__ +#elif defined(__powerpc__) || defined(_MAC) /* ? */ # define __RPC_MAC__ /* Also define __RPC_WIN32__ to ensure compatibility */ # define __RPC_WIN32__ diff --git a/include/windef.h b/include/windef.h index ea9f32b5a0..82e9ab968c 100644 --- a/include/windef.h +++ b/include/windef.h @@ -80,6 +80,9 @@ extern "C" { # define __stdcall __attribute__((pcs("aapcs-vfp"))) # elif defined(__aarch64__) && defined (__GNUC__) # define __stdcall __attribute__((ms_abi)) +# elif defined(__powerpc64__) && defined (__GNUC__) + /* ppc64 relies on long calls being generated for thunks (r2 save / restore) */ +# define __stdcall __attribute__((__longcall__)) # else /* __i386__ */ # define __stdcall # endif /* __i386__ */ @@ -102,6 +105,9 @@ extern "C" { # define __cdecl __attribute__((pcs("aapcs-vfp"))) # elif defined(__aarch64__) && defined (__GNUC__) # define __cdecl __attribute__((ms_abi)) +# elif defined(__powerpc64__) && defined (__GNUC__) + /* ppc64 relies on long calls being generated for thunks (r2 save / restore) */ +# define __cdecl __attribute__((__longcall__)) # elif !defined(_MSC_VER) # define __cdecl # endif diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 63f65cd00f..450ec9b39c 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -117,7 +117,7 @@ typedef union
enum cpu_type { - CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64 + CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64, CPU_POWERPC64 }; typedef int cpu_type_t;
@@ -132,6 +132,7 @@ typedef struct struct { unsigned __int64 rip, rbp, rsp; unsigned int cs, ss, flags, __pad; } x86_64_regs; struct { unsigned int iar, msr, ctr, lr, dar, dsisr, trap, __pad; } powerpc_regs; + struct { unsigned __int64 iar, msr, ctr, lr, dar, dsisr, trap, __pad; } powerpc64_regs; struct { unsigned int sp, lr, pc, cpsr; } arm_regs; struct { unsigned __int64 sp, pc, pstate; } arm64_regs; } ctl; @@ -141,6 +142,7 @@ typedef struct struct { unsigned __int64 rax,rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15; } x86_64_regs; struct { unsigned int gpr[32], cr, xer; } powerpc_regs; + struct { unsigned __int64 gpr[32], cr, xer; } powerpc64_regs; struct { unsigned int r[13]; } arm_regs; struct { unsigned __int64 x[31]; } arm64_regs; } integer; @@ -155,6 +157,7 @@ typedef struct unsigned char regs[80]; } i386_regs; struct { struct { unsigned __int64 low, high; } fpregs[32]; } x86_64_regs; struct { double fpr[32], fpscr; } powerpc_regs; + struct { double fpr[32], fpscr; } powerpc64_regs; struct { unsigned __int64 d[32]; unsigned int fpscr; } arm_regs; struct { unsigned __int64 d[64]; unsigned int fpcr, fpsr; } arm64_regs; } fp; @@ -163,6 +166,7 @@ typedef struct struct { unsigned int dr0, dr1, dr2, dr3, dr6, dr7; } i386_regs; struct { unsigned __int64 dr0, dr1, dr2, dr3, dr6, dr7; } x86_64_regs; struct { unsigned int dr[8]; } powerpc_regs; + struct { unsigned __int64 dr[8]; } powerpc64_regs; struct { unsigned int bvr[8], bcr[8], wvr[1], wcr[1]; } arm_regs; struct { unsigned __int64 bvr[8], wvr[2]; unsigned int bcr[8], wcr[2]; } arm64_regs; } debug; diff --git a/include/winnt.h b/include/winnt.h index 5694ad7c01..74a55cb5b5 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -2,6 +2,7 @@ * Win32 definitions for Windows NT * * Copyright 1996 Alexandre Julliard + * Copyright 2019 Timothy Pearson tpearson@raptorengineering.com (PowerPC 64) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -655,6 +656,7 @@ typedef DWORD FLONG; #define PROCESSOR_ARCHITECTURE_ARM64 12 #define PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64 13 #define PROCESSOR_ARCHITECTURE_IA32_ON_ARM64 14 +#define PROCESSOR_ARCHITECTURE_PPC64 15 #define PROCESSOR_ARCHITECTURE_UNKNOWN 0xFFFF
/* dwProcessorType */ @@ -672,6 +674,7 @@ typedef DWORD FLONG; #define PROCESSOR_PPC_603 603 #define PROCESSOR_PPC_604 604 #define PROCESSOR_PPC_620 620 +#define PROCESSOR_PPC64_OP 690 #define PROCESSOR_HITACHI_SH3 10003 #define PROCESSOR_HITACHI_SH3E 10004 #define PROCESSOR_HITACHI_SH4 10005 @@ -1985,8 +1988,138 @@ typedef struct _CONTEXT
#endif /* _MIPS_ */
-/* PowerPC context definitions */ -#ifdef __powerpc__ +/* PowerPC 64-bit context definitions */ +#if defined(__powerpc64__) + +#define CONTEXT_CONTROL 0x0001 +#define CONTEXT_FLOATING_POINT 0x0002 +#define CONTEXT_INTEGER 0x0004 +#define CONTEXT_DEBUG_REGISTERS 0x0008 +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER) +#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | \ + CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS) + +#define EXCEPTION_READ_FAULT 0 +#define EXCEPTION_WRITE_FAULT 1 +#define EXCEPTION_EXECUTE_FAULT 8 + +typedef struct +{ + /* These are selected by CONTEXT_FLOATING_POINT */ + double Fpr0; + double Fpr1; + double Fpr2; + double Fpr3; + double Fpr4; + double Fpr5; + double Fpr6; + double Fpr7; + double Fpr8; + double Fpr9; + double Fpr10; + double Fpr11; + double Fpr12; + double Fpr13; + double Fpr14; + double Fpr15; + double Fpr16; + double Fpr17; + double Fpr18; + double Fpr19; + double Fpr20; + double Fpr21; + double Fpr22; + double Fpr23; + double Fpr24; + double Fpr25; + double Fpr26; + double Fpr27; + double Fpr28; + double Fpr29; + double Fpr30; + double Fpr31; + double Fpscr; + + /* These are selected by CONTEXT_INTEGER */ + DWORD64 Gpr0; + DWORD64 Gpr1; + DWORD64 Gpr2; + DWORD64 Gpr3; + DWORD64 Gpr4; + DWORD64 Gpr5; + DWORD64 Gpr6; + DWORD64 Gpr7; + DWORD64 Gpr8; + DWORD64 Gpr9; + DWORD64 Gpr10; + DWORD64 Gpr11; + DWORD64 Gpr12; + DWORD64 Gpr13; + DWORD64 Gpr14; + DWORD64 Gpr15; + DWORD64 Gpr16; + DWORD64 Gpr17; + DWORD64 Gpr18; + DWORD64 Gpr19; + DWORD64 Gpr20; + DWORD64 Gpr21; + DWORD64 Gpr22; + DWORD64 Gpr23; + DWORD64 Gpr24; + DWORD64 Gpr25; + DWORD64 Gpr26; + DWORD64 Gpr27; + DWORD64 Gpr28; + DWORD64 Gpr29; + DWORD64 Gpr30; + DWORD64 Gpr31; + + DWORD64 Cr; + DWORD64 Xer; + + /* These are selected by CONTEXT_CONTROL */ + DWORD64 Msr; + DWORD64 Iar; /* Instruction Address Register , aka PC ... */ + DWORD64 Lr; + DWORD64 Ctr; + + DWORD64 ContextFlags; + + DWORD64 Dar; /* Fault registers for coredump */ + DWORD64 Dsisr; + DWORD64 Trap; /* number of powerpc exception taken */ + + /* These are selected by CONTEXT_DEBUG_REGISTERS */ + DWORD64 Dr0; + DWORD64 Dr1; + DWORD64 Dr2; + DWORD64 Dr3; + DWORD64 Dr4; + DWORD64 Dr5; + DWORD64 Dr6; + DWORD64 Dr7; +} CONTEXT; + +typedef struct _STACK_FRAME_HEADER +{ + DWORD BackChain; + DWORD GlueSaved1; + DWORD GlueSaved2; + DWORD Reserved1; + DWORD Spare1; + DWORD Spare2; + + DWORD Parameter0; + DWORD Parameter1; + DWORD Parameter2; + DWORD Parameter3; + DWORD Parameter4; + DWORD Parameter5; + DWORD Parameter6; + DWORD Parameter7; +} STACK_FRAME_HEADER,*PSTACK_FRAME_HEADER; + +#elif defined(__powerpc__)
#define CONTEXT_CONTROL 0x0001 #define CONTEXT_FLOATING_POINT 0x0002 @@ -2729,6 +2862,7 @@ typedef struct _IMAGE_VXD_HEADER { #define IMAGE_FILE_MACHINE_AM33 0x01d3 #define IMAGE_FILE_MACHINE_POWERPC 0x01f0 #define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 +#define IMAGE_FILE_MACHINE_POWERPC64 0x01f2 #define IMAGE_FILE_MACHINE_IA64 0x0200 #define IMAGE_FILE_MACHINE_MIPS16 0x0266 #define IMAGE_FILE_MACHINE_ALPHA64 0x0284 diff --git a/libs/port/interlocked.c b/libs/port/interlocked.c index efdfd2af19..6cb1b56bd5 100644 --- a/libs/port/interlocked.c +++ b/libs/port/interlocked.c @@ -180,7 +180,7 @@ __ASM_GLOBAL_FUNC(interlocked_cmpxchg128, __ASM_CFI(".cfi_same_value %rbx\n\t") "ret")
-#elif defined(__powerpc__) +#elif defined(__powerpc__) && !defined(__powerpc64__)
#if !(defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) && __SIZEOF_POINTER__ == 4) \ && !(defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) && __SIZEOF_POINTER__ == 8) diff --git a/libs/wine/port.c b/libs/wine/port.c index 29e9091789..702225b110 100644 --- a/libs/wine/port.c +++ b/libs/wine/port.c @@ -2,6 +2,7 @@ * Wine portability routines * * Copyright 2000 Alexandre Julliard + * Copyright 2019 Timothy Pearson tpearson@raptorengineering.com (PowerPC 64) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -147,6 +148,24 @@ __ASM_GLOBAL_FUNC( wine_call_on_stack, __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t") __ASM_CFI(".cfi_same_value %rbp\n\t") "ret") +#elif defined(__powerpc64__) && defined(__GNUC__) +__ASM_GLOBAL_FUNC( wine_call_on_stack, + "mflr 0\n\t" /* get return address */ + "std 0, 16(1)\n\t" /* save return address on stack */ + "subi 5, 5, 112\n\t" /* reserve space on new stack */ + "std 1, 48(5)\n\t" /* store old sp */ + "mr 12, 3\n\t" /* func -> r12: ppc64 v2 requires r12 == ctr before bctr for TOC setup */ + "mtctr 12\n\t" /* func -> ctr */ + "mr 3, 4\n\t" /* args -> function param 1 (r3) */ + "mr 1, 5\n\t" /* stack */ + "li 0, 0\n\t" /* zero */ + "std 0, 0(1)\n\t" /* bottom of stack */ + "stdu 1, -112(1)\n\t" /* create a frame for this function */ + "bctrl\n\t" /* call ctr */ + "ld 1, 160(1)\n\t" /* fetch old sp */ + "ld 0, 16(1)\n\t" /* fetch return address */ + "mtlr 0\n\t" /* return address -> lr */ + "blr") /* return */ #elif defined(__powerpc__) && defined(__GNUC__) __ASM_GLOBAL_FUNC( wine_call_on_stack, "mflr 0\n\t" /* get return address */ diff --git a/programs/winedbg/Makefile.in b/programs/winedbg/Makefile.in index 22c4cd23e8..6bd4a2c2a6 100644 --- a/programs/winedbg/Makefile.in +++ b/programs/winedbg/Makefile.in @@ -9,6 +9,7 @@ C_SRCS = \ be_arm64.c \ be_i386.c \ be_ppc.c \ + be_ppc64.c \ be_x86_64.c \ break.c \ crashdlg.c \ diff --git a/programs/winedbg/be_ppc.c b/programs/winedbg/be_ppc.c index ff6ece6df3..ff264ed83e 100644 --- a/programs/winedbg/be_ppc.c +++ b/programs/winedbg/be_ppc.c @@ -21,7 +21,7 @@
#include "debugger.h"
-#if defined(__powerpc__) +#if defined(__powerpc__) && !defined(__powerpc64__)
static BOOL be_ppc_get_addr(HANDLE hThread, const dbg_ctx_t *ctx, enum be_cpu_addr bca, ADDRESS64* addr) diff --git a/programs/winedbg/be_ppc64.c b/programs/winedbg/be_ppc64.c new file mode 100644 index 0000000000..c342df9f78 --- /dev/null +++ b/programs/winedbg/be_ppc64.c @@ -0,0 +1,303 @@ +/* + * Debugger Power PC specific functions + * + * Copyright 2000-2003 Marcus Meissner + * 2004 Eric Pouech + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "debugger.h" + +#if defined(__powerpc64__) + +static BOOL be_ppc_get_addr(HANDLE hThread, const dbg_ctx_t *ctx, + enum be_cpu_addr bca, ADDRESS64* addr) +{ + switch (bca) + { + case be_cpu_addr_pc: + return be_cpu_build_addr(hThread, ctx, addr, 0, ctx->ctx.Iar); + default: + case be_cpu_addr_stack: + case be_cpu_addr_frame: + dbg_printf("not done\n"); + } + return FALSE; +} + +static BOOL be_ppc_get_register_info(int regno, enum be_cpu_addr* kind) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static void be_ppc_single_step(dbg_ctx_t *ctx, BOOL enable) +{ +#ifndef MSR_SE +# define MSR_SE (1<<10) +#endif + if (enable) ctx->ctx.Msr |= MSR_SE; + else ctx->ctx.Msr &= ~MSR_SE; +} + +static void be_ppc_print_context(HANDLE hThread, const dbg_ctx_t *ctx, int all_regs) +{ + dbg_printf("Context printing for PPC not done yet\n"); +} + +static void be_ppc_print_segment_info(HANDLE hThread, const dbg_ctx_t *ctx) +{ +} + +static struct dbg_internal_var be_ppc_ctx[] = +{ + {0, NULL, 0, dbg_itype_none} +}; + +static BOOL be_ppc_is_step_over_insn(const void* insn) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static BOOL be_ppc_is_function_return(const void* insn) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static BOOL be_ppc_is_break_insn(const void* insn) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static BOOL be_ppc_is_func_call(const void* insn, ADDRESS64* callee) +{ + return FALSE; +} + +static BOOL be_ppc_is_jump(const void* insn, ADDRESS64* jumpee) +{ + return FALSE; +} + +static void be_ppc_disasm_one_insn(ADDRESS64* addr, int display) + +{ + dbg_printf("Disasm NIY\n"); +} + +static BOOL be_ppc_insert_Xpoint(HANDLE hProcess, const struct be_process_io* pio, + dbg_ctx_t *ctx, enum be_xpoint_type type, + void* addr, unsigned long* val, unsigned size) +{ + unsigned long xbp; + SIZE_T sz; + + switch (type) + { + case be_xpoint_break: + if (!size) return FALSE; + if (!pio->read(hProcess, addr, val, 4, &sz) || sz != 4) return FALSE; + xbp = 0x7d821008; /* 7d 82 10 08 ... in big endian */ + if (!pio->write(hProcess, addr, &xbp, 4, &sz) || sz != 4) return FALSE; + break; + default: + dbg_printf("Unknown/unsupported bp type %c\n", type); + return FALSE; + } + return TRUE; +} + +static BOOL be_ppc_remove_Xpoint(HANDLE hProcess, const struct be_process_io* pio, + dbg_ctx_t *ctx, enum be_xpoint_type type, + void* addr, unsigned long val, unsigned size) +{ + SIZE_T sz; + + switch (type) + { + case be_xpoint_break: + if (!size) return FALSE; + if (!pio->write(hProcess, addr, &val, 4, &sz) || sz == 4) return FALSE; + break; + default: + dbg_printf("Unknown/unsupported bp type %c\n", type); + return FALSE; + } + return TRUE; +} + +static BOOL be_ppc_is_watchpoint_set(const dbg_ctx_t *ctx, unsigned idx) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static void be_ppc_clear_watchpoint(dbg_ctx_t *ctx, unsigned idx) +{ + dbg_printf("not done\n"); +} + +static int be_ppc_adjust_pc_for_break(dbg_ctx_t *ctx, BOOL way) +{ + dbg_printf("not done\n"); + return 0; +} + +static BOOL be_ppc_fetch_integer(const struct dbg_lvalue* lvalue, unsigned size, + BOOL is_signed, LONGLONG* ret) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static BOOL be_ppc_fetch_float(const struct dbg_lvalue* lvalue, unsigned size, + long double* ret) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static BOOL be_ppc_store_integer(const struct dbg_lvalue* lvalue, unsigned size, + BOOL is_signed, LONGLONG val) +{ + dbg_printf("be_ppc_store_integer: not done\n"); + return FALSE; +} + +static BOOL be_ppc_get_context(HANDLE thread, dbg_ctx_t *ctx) +{ + ctx->ctx.ContextFlags = CONTEXT_ALL; + return GetThreadContext(thread, &ctx->ctx); +} + +static BOOL be_ppc_set_context(HANDLE thread, const dbg_ctx_t *ctx) +{ + return SetThreadContext(thread, &ctx->ctx); +} + +#define REG(r,gs) {FIELD_OFFSET(CONTEXT, r), sizeof(((CONTEXT*)NULL)->r), gs} + +static struct gdb_register be_ppc_gdb_register_map[] = { + REG(Gpr0, 4), + REG(Gpr1, 4), + REG(Gpr2, 4), + REG(Gpr3, 4), + REG(Gpr4, 4), + REG(Gpr5, 4), + REG(Gpr6, 4), + REG(Gpr7, 4), + REG(Gpr8, 4), + REG(Gpr9, 4), + REG(Gpr10, 4), + REG(Gpr11, 4), + REG(Gpr12, 4), + REG(Gpr13, 4), + REG(Gpr14, 4), + REG(Gpr15, 4), + REG(Gpr16, 4), + REG(Gpr17, 4), + REG(Gpr18, 4), + REG(Gpr19, 4), + REG(Gpr20, 4), + REG(Gpr21, 4), + REG(Gpr22, 4), + REG(Gpr23, 4), + REG(Gpr24, 4), + REG(Gpr25, 4), + REG(Gpr26, 4), + REG(Gpr27, 4), + REG(Gpr28, 4), + REG(Gpr29, 4), + REG(Gpr30, 4), + REG(Gpr31, 4), + REG(Fpr0, 4), + REG(Fpr1, 4), + REG(Fpr2, 4), + REG(Fpr3, 4), + REG(Fpr4, 4), + REG(Fpr5, 4), + REG(Fpr6, 4), + REG(Fpr7, 4), + REG(Fpr8, 4), + REG(Fpr9, 4), + REG(Fpr10, 4), + REG(Fpr11, 4), + REG(Fpr12, 4), + REG(Fpr13, 4), + REG(Fpr14, 4), + REG(Fpr15, 4), + REG(Fpr16, 4), + REG(Fpr17, 4), + REG(Fpr18, 4), + REG(Fpr19, 4), + REG(Fpr20, 4), + REG(Fpr21, 4), + REG(Fpr22, 4), + REG(Fpr23, 4), + REG(Fpr24, 4), + REG(Fpr25, 4), + REG(Fpr26, 4), + REG(Fpr27, 4), + REG(Fpr28, 4), + REG(Fpr29, 4), + REG(Fpr30, 4), + REG(Fpr31, 4), + + REG(Iar, 4), + REG(Msr, 4), + REG(Cr, 4), + REG(Lr, 4), + REG(Ctr, 4), + REG(Xer, 4), + /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */ + /* see gdb/nlm/ppc.c */ +}; + +struct backend_cpu be_ppc64 = +{ + IMAGE_FILE_MACHINE_POWERPC64, + 8, + be_cpu_linearize, + be_cpu_build_addr, + be_ppc_get_addr, + be_ppc_get_register_info, + be_ppc_single_step, + be_ppc_print_context, + be_ppc_print_segment_info, + be_ppc_ctx, + be_ppc_is_step_over_insn, + be_ppc_is_function_return, + be_ppc_is_break_insn, + be_ppc_is_func_call, + be_ppc_is_jump, + be_ppc_disasm_one_insn, + be_ppc_insert_Xpoint, + be_ppc_remove_Xpoint, + be_ppc_is_watchpoint_set, + be_ppc_clear_watchpoint, + be_ppc_adjust_pc_for_break, + be_ppc_fetch_integer, + be_ppc_fetch_float, + be_ppc_store_integer, + be_ppc_get_context, + be_ppc_set_context, + be_ppc_gdb_register_map, + ARRAY_SIZE(be_ppc_gdb_register_map), +}; +#endif diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c index b7f59ee05b..8baa35b0a4 100644 --- a/programs/winedbg/gdbproxy.c +++ b/programs/winedbg/gdbproxy.c @@ -179,6 +179,8 @@ static unsigned char checksum(const char* ptr, int len)
#ifdef __i386__ static const char target_xml[] = ""; +#elif defined(__powerpc64__) +static const char target_xml[] = ""; #elif defined(__powerpc__) static const char target_xml[] = ""; #elif defined(__x86_64__) diff --git a/programs/winedbg/tgt_active.c b/programs/winedbg/tgt_active.c index 5385d0effa..5e010a1c1c 100644 --- a/programs/winedbg/tgt_active.c +++ b/programs/winedbg/tgt_active.c @@ -732,6 +732,8 @@ static void output_system_info(void) static const char platform[] = "i386"; #elif defined(__x86_64__) static const char platform[] = "x86_64"; +#elif defined(__powerpc64__) + static const char platform[] = "powerpc64"; #elif defined(__powerpc__) static const char platform[] = "powerpc"; #elif defined(__arm__) diff --git a/programs/winedbg/tgt_minidump.c b/programs/winedbg/tgt_minidump.c index 95af7a601e..295e3e2b4d 100644 --- a/programs/winedbg/tgt_minidump.c +++ b/programs/winedbg/tgt_minidump.c @@ -291,6 +291,9 @@ static enum dbg_start minidump_do_reload(struct tgt_process_minidump_data* data) case PROCESSOR_ARCHITECTURE_PPC: str = "PowerPC"; break; + case PROCESSOR_ARCHITECTURE_PPC64: + str = "PowerPC 64"; + break; case PROCESSOR_ARCHITECTURE_AMD64: str = "X86_64"; break; diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c index 8634c0f73f..c4d7ccdac1 100644 --- a/programs/winedbg/winedbg.c +++ b/programs/winedbg/winedbg.c @@ -281,6 +281,8 @@ struct dbg_process* dbg_get_process_h(HANDLE h)
#ifdef __i386__ extern struct backend_cpu be_i386; +#elif defined(__powerpc64__) +extern struct backend_cpu be_ppc64; #elif defined(__powerpc__) extern struct backend_cpu be_ppc; #elif defined(__x86_64__) @@ -330,6 +332,8 @@ struct dbg_process* dbg_add_process(const struct be_process_io* pio, DWORD pid,
#ifdef __i386__ p->be_cpu = &be_i386; +#elif defined(__powerpc64__) + p->be_cpu = &be_ppc64; #elif defined(__powerpc__) p->be_cpu = &be_ppc; #elif defined(__x86_64__) diff --git a/programs/winetest/main.c b/programs/winetest/main.c index 3d6cc660ec..44a9963d17 100644 --- a/programs/winetest/main.c +++ b/programs/winetest/main.c @@ -343,6 +343,8 @@ static void print_version (void) static const char platform[] = "i386"; #elif defined(__x86_64__) static const char platform[] = "x86_64"; +#elif defined(__powerpc64__) + static const char platform[] = "powerpc64"; #elif defined(__powerpc__) static const char platform[] = "powerpc"; #elif defined(__arm__) diff --git a/server/mapping.c b/server/mapping.c index 085d7aaa30..7c2d5316fe 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -2,6 +2,7 @@ * Server-side file mapping management * * Copyright (C) 1999 Alexandre Julliard + * Copyright 2019 Timothy Pearson tpearson@raptorengineering.com (PowerPC 64) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -619,7 +620,7 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s return STATUS_INVALID_IMAGE_FORMAT; case IMAGE_FILE_MACHINE_POWERPC: mapping->image.cpu = CPU_POWERPC; - if (cpu_mask & CPU_FLAG(CPU_POWERPC)) break; + if (cpu_mask & (CPU_FLAG(CPU_POWERPC) | CPU_FLAG(CPU_POWERPC64))) break; return STATUS_INVALID_IMAGE_FORMAT; default: return STATUS_INVALID_IMAGE_FORMAT; @@ -661,6 +662,10 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s mapping->image.cpu = CPU_ARM64; if (cpu_mask & (CPU_FLAG(CPU_ARM) | CPU_FLAG(CPU_ARM64))) break; return STATUS_INVALID_IMAGE_FORMAT; + case IMAGE_FILE_MACHINE_POWERPC64: + mapping->image.cpu = CPU_POWERPC64; + if (cpu_mask & (CPU_FLAG(CPU_POWERPC) | CPU_FLAG(CPU_POWERPC64))) break; + return STATUS_INVALID_IMAGE_FORMAT; default: return STATUS_INVALID_IMAGE_FORMAT; } @@ -726,6 +731,7 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s mapping->image.image_flags |= IMAGE_FLAGS_ComPlusNativeReady; if (cpu_mask & CPU_FLAG(CPU_x86_64)) mapping->image.cpu = CPU_x86_64; else if (cpu_mask & CPU_FLAG(CPU_ARM64)) mapping->image.cpu = CPU_ARM64; + else if (cpu_mask & CPU_FLAG(CPU_POWERPC64)) mapping->image.cpu = CPU_POWERPC64; } }
diff --git a/server/process.h b/server/process.h index 4566a04b48..b65c36d0e8 100644 --- a/server/process.h +++ b/server/process.h @@ -108,7 +108,7 @@ struct process_snapshot };
#define CPU_FLAG(cpu) (1 << (cpu)) -#define CPU_64BIT_MASK (CPU_FLAG(CPU_x86_64) | CPU_FLAG(CPU_ARM64)) +#define CPU_64BIT_MASK (CPU_FLAG(CPU_x86_64) | CPU_FLAG(CPU_ARM64) | CPU_FLAG(CPU_POWERPC64))
/* process functions */
diff --git a/server/protocol.def b/server/protocol.def index e65b984a44..0fa5513285 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -133,7 +133,7 @@ typedef union /* supported CPU types */ enum cpu_type { - CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64 + CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64, CPU_POWERPC64 }; typedef int cpu_type_t;
@@ -148,6 +148,7 @@ typedef struct struct { unsigned __int64 rip, rbp, rsp; unsigned int cs, ss, flags, __pad; } x86_64_regs; struct { unsigned int iar, msr, ctr, lr, dar, dsisr, trap, __pad; } powerpc_regs; + struct { unsigned __int64 iar, msr, ctr, lr, dar, dsisr, trap, __pad; } powerpc64_regs; struct { unsigned int sp, lr, pc, cpsr; } arm_regs; struct { unsigned __int64 sp, pc, pstate; } arm64_regs; } ctl; /* selected by SERVER_CTX_CONTROL */ @@ -157,6 +158,7 @@ typedef struct struct { unsigned __int64 rax,rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15; } x86_64_regs; struct { unsigned int gpr[32], cr, xer; } powerpc_regs; + struct { unsigned __int64 gpr[32], cr, xer; } powerpc64_regs; struct { unsigned int r[13]; } arm_regs; struct { unsigned __int64 x[31]; } arm64_regs; } integer; /* selected by SERVER_CTX_INTEGER */ @@ -171,6 +173,7 @@ typedef struct unsigned char regs[80]; } i386_regs; struct { struct { unsigned __int64 low, high; } fpregs[32]; } x86_64_regs; struct { double fpr[32], fpscr; } powerpc_regs; + struct { double fpr[32], fpscr; } powerpc64_regs; struct { unsigned __int64 d[32]; unsigned int fpscr; } arm_regs; struct { unsigned __int64 d[64]; unsigned int fpcr, fpsr; } arm64_regs; } fp; /* selected by SERVER_CTX_FLOATING_POINT */ @@ -179,6 +182,7 @@ typedef struct struct { unsigned int dr0, dr1, dr2, dr3, dr6, dr7; } i386_regs; struct { unsigned __int64 dr0, dr1, dr2, dr3, dr6, dr7; } x86_64_regs; struct { unsigned int dr[8]; } powerpc_regs; + struct { unsigned __int64 dr[8]; } powerpc64_regs; struct { unsigned int bvr[8], bcr[8], wvr[1], wcr[1]; } arm_regs; struct { unsigned __int64 bvr[8], wvr[2]; unsigned int bcr[8], wcr[2]; } arm64_regs; } debug; /* selected by SERVER_CTX_DEBUG_REGISTERS */ diff --git a/server/thread.c b/server/thread.c index 4c3d9c3d16..5571036077 100644 --- a/server/thread.c +++ b/server/thread.c @@ -57,6 +57,8 @@ static const unsigned int supported_cpus = CPU_FLAG(CPU_x86); #elif defined(__x86_64__) static const unsigned int supported_cpus = CPU_FLAG(CPU_x86_64) | CPU_FLAG(CPU_x86); +#elif defined(__powerpc64__) +static const unsigned int supported_cpus = CPU_FLAG(CPU_POWERPC64); #elif defined(__powerpc__) static const unsigned int supported_cpus = CPU_FLAG(CPU_POWERPC); #elif defined(__arm__) @@ -1182,6 +1184,7 @@ static unsigned int get_context_system_regs( enum cpu_type cpu ) case CPU_x86: return SERVER_CTX_DEBUG_REGISTERS; case CPU_x86_64: return SERVER_CTX_DEBUG_REGISTERS; case CPU_POWERPC: return 0; + case CPU_POWERPC64: return 0; case CPU_ARM: return SERVER_CTX_DEBUG_REGISTERS; case CPU_ARM64: return SERVER_CTX_DEBUG_REGISTERS; } @@ -1210,6 +1213,9 @@ void break_thread( struct thread *thread ) case CPU_POWERPC: data.exception.address = thread->context->ctl.powerpc_regs.iar; break; + case CPU_POWERPC64: + data.exception.address = thread->context->ctl.powerpc64_regs.iar; + break; case CPU_ARM: data.exception.address = thread->context->ctl.arm_regs.pc; break; diff --git a/server/trace.c b/server/trace.c index 41bbe4a516..5a9e25656d 100644 --- a/server/trace.c +++ b/server/trace.c @@ -137,6 +137,7 @@ static void dump_cpu_type( const char *prefix, const cpu_type_t *code ) CASE(x86); CASE(x86_64); CASE(POWERPC); + CASE(POWERPC64); CASE(ARM); CASE(ARM64); default: fprintf( stderr, "%s%u", prefix, *code ); break; @@ -657,6 +658,26 @@ static void dump_varargs_context( const char *prefix, data_size_t size ) fprintf( stderr, ",fpscr=%g", ctx.fp.powerpc_regs.fpscr ); } break; + case CPU_POWERPC64: + if (ctx.flags & SERVER_CTX_CONTROL) + fprintf( stderr, ",iar=%016x,msr=%016x,ctr=%016x,lr=%016x,dar=%016x,dsisr=%016x,trap=%016x", + ctx.ctl.powerpc64_regs.iar, ctx.ctl.powerpc64_regs.msr, ctx.ctl.powerpc64_regs.ctr, + ctx.ctl.powerpc64_regs.lr, ctx.ctl.powerpc64_regs.dar, ctx.ctl.powerpc64_regs.dsisr, + ctx.ctl.powerpc64_regs.trap ); + if (ctx.flags & SERVER_CTX_INTEGER) + { + for (i = 0; i < 32; i++) fprintf( stderr, ",gpr%u=%016x", i, ctx.integer.powerpc64_regs.gpr[i] ); + fprintf( stderr, ",cr=%08x,xer=%08x", + ctx.integer.powerpc64_regs.cr, ctx.integer.powerpc64_regs.xer ); + } + if (ctx.flags & SERVER_CTX_DEBUG_REGISTERS) + for (i = 0; i < 8; i++) fprintf( stderr, ",dr%u=%016x", i, ctx.debug.powerpc64_regs.dr[i] ); + if (ctx.flags & SERVER_CTX_FLOATING_POINT) + { + for (i = 0; i < 32; i++) fprintf( stderr, ",fpr%u=%g", i, ctx.fp.powerpc64_regs.fpr[i] ); + fprintf( stderr, ",fpscr=%g", ctx.fp.powerpc64_regs.fpscr ); + } + break; case CPU_ARM: if (ctx.flags & SERVER_CTX_CONTROL) fprintf( stderr, ",sp=%08x,lr=%08x,pc=%08x,cpsr=%08x", diff --git a/tools/widl/widl.c b/tools/widl/widl.c index 0bcf67ba73..8b44d5a70f 100644 --- a/tools/widl/widl.c +++ b/tools/widl/widl.c @@ -95,6 +95,8 @@ static const char version_string[] = "Wine IDL Compiler version " PACKAGE_VERSIO enum target_cpu target_cpu = CPU_x86; #elif defined(__x86_64__) enum target_cpu target_cpu = CPU_x86_64; +#elif defined(__powerpc64__) +enum target_cpu target_cpu = CPU_POWERPC64; #elif defined(__powerpc__) enum target_cpu target_cpu = CPU_POWERPC; #elif defined(__arm__) @@ -286,6 +288,7 @@ static void set_target( const char *target ) { "amd64", CPU_x86_64 }, { "x86_64", CPU_x86_64 }, { "powerpc", CPU_POWERPC }, + { "powerpc64", CPU_POWERPC64 }, { "arm", CPU_ARM }, { "armv5", CPU_ARM }, { "armv6", CPU_ARM }, @@ -751,6 +754,10 @@ int main(int argc,char *argv[]) if (pointer_size == 4) error( "Cannot build 32-bit code for this CPU\n" ); pointer_size = 8; break; + case CPU_POWERPC64: + if (pointer_size == 4) error( "Cannot build 32-bit code for this CPU\n" ); + pointer_size = 8; + break; default: if (pointer_size == 8) error( "Cannot build 64-bit code for this CPU\n" ); pointer_size = 4; diff --git a/tools/widl/widl.h b/tools/widl/widl.h index 4f4252e3ea..bc6226c54f 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -76,7 +76,7 @@ extern int char_number;
enum target_cpu { - CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64, CPU_LAST = CPU_ARM64 + CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64, CPU_POWERPC64, CPU_LAST = CPU_POWERPC64 };
extern enum target_cpu target_cpu; diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index cb4f0f38dd..95c65ce2f6 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -2159,7 +2159,7 @@ static void add_union_typeinfo(msft_typelib_t *typelib, type_t *tunion) var_t *cur; msft_typeinfo_t *msft_typeinfo;
- if (-1 < tunion->typelib_idx) + if (-1 <= tunion->typelib_idx) return;
tunion->typelib_idx = typelib->typelib_header.nrtypeinfos; diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index fbc2cd9a00..61a5b05d2f 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -142,7 +142,7 @@ typedef struct
enum target_cpu { - CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64, CPU_LAST = CPU_ARM64 + CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64, CPU_POWERPC64, CPU_LAST = CPU_POWERPC64 };
enum target_platform @@ -180,7 +180,7 @@ struct strarray
#define FLAG_CPU(cpu) (0x01000 << (cpu)) #define FLAG_CPU_MASK (FLAG_CPU(CPU_LAST + 1) - FLAG_CPU(0)) -#define FLAG_CPU_WIN64 (FLAG_CPU(CPU_x86_64) | FLAG_CPU(CPU_ARM64)) +#define FLAG_CPU_WIN64 (FLAG_CPU(CPU_x86_64) | FLAG_CPU(CPU_ARM64) | FLAG_CPU(CPU_POWERPC64)) #define FLAG_CPU_WIN32 (FLAG_CPU_MASK & ~FLAG_CPU_WIN64)
#define MAX_ORDINALS 65535 diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 5e5866c80f..b700e8e8e0 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -3,6 +3,7 @@ * * Copyright 2000, 2004 Alexandre Julliard * Copyright 2000 Eric Pouech + * Copyright 2019 Timothy Pearson tpearson@raptorengineering.com (PowerPC 64) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -694,6 +695,20 @@ static void output_import_thunk( const char *name, const char *table, int pos ) output( "\tmr %s, %s\n", ppc_reg(31), ppc_reg(0) ); output( "\tbctr\n" ); break; + case CPU_POWERPC64: + /* + * The ppc64 ABI v2 expects r12 to be set to ctr before bctr for PLT-like calls. + * ABIv2-compatible functions attempt to rebuild the TOC pointer (r2) from r12 under this assumption. + */ + output( "\tlis %s, (%s+%d)@highest\n", ppc_reg(12), table, pos ); + output( "\tori %s, %s, (%s+%d)@higher\n", ppc_reg(12), ppc_reg(12), table, pos ); + output( "\trldicr %s, %s, 32, 31\n", ppc_reg(12), ppc_reg(12) ); + output( "\toris %s, %s, (%s+%d)@high\n", ppc_reg(12), ppc_reg(12), table, pos ); + output( "\tori %s, %s, (%s+%d)@l\n", ppc_reg(12), ppc_reg(12), table, pos ); + output( "\tld %s, 0(%s)\n", ppc_reg(12), ppc_reg(12) ); + output( "\tmtctr %s\n", ppc_reg(12) ); + output( "\tbctr\n" ); + break; } output_cfi( ".cfi_endproc" ); output_function_size( name ); @@ -1042,6 +1057,62 @@ static void output_delayed_import_thunks( const DLLSPEC *spec ) output( "\tmtlr %s\n", ppc_reg(0)); output( "\taddi %s, %s, %d\n", ppc_reg(1), ppc_reg(1), 48+extra_stack_storage);
+ /* branch to ctr register. */ + output( "\tbctr\n"); + break; + case CPU_POWERPC64: + /* Save all callee saved registers into a stackframe. */ + output( "\tstdu %s, -%d(%s)\n",ppc_reg(1), 168+extra_stack_storage, ppc_reg(1)); + output( "\tstd %s, %d(%s)\n", ppc_reg(3), 48+extra_stack_storage, ppc_reg(1)); + output( "\tstd %s, %d(%s)\n", ppc_reg(4), 56+extra_stack_storage, ppc_reg(1)); + output( "\tstd %s, %d(%s)\n", ppc_reg(5), 64+extra_stack_storage, ppc_reg(1)); + output( "\tstd %s, %d(%s)\n", ppc_reg(6), 72+extra_stack_storage, ppc_reg(1)); + output( "\tstd %s, %d(%s)\n", ppc_reg(7), 80+extra_stack_storage, ppc_reg(1)); + output( "\tstd %s, %d(%s)\n", ppc_reg(8), 88+extra_stack_storage, ppc_reg(1)); + output( "\tstd %s, %d(%s)\n", ppc_reg(9), 96+extra_stack_storage, ppc_reg(1)); + output( "\tstd %s, %d(%s)\n", ppc_reg(10),104+extra_stack_storage, ppc_reg(1)); + output( "\tstd %s, %d(%s)\n", ppc_reg(11),112+extra_stack_storage, ppc_reg(1)); + output( "\tstd %s, %d(%s)\n", ppc_reg(12),120+extra_stack_storage, ppc_reg(1)); + + /* r0 -> r3 (arg1) */ + output( "\tmr %s, %s\n", ppc_reg(3), ppc_reg(0)); + + /* save return address */ + output( "\tmflr %s\n", ppc_reg(0)); + output( "\tstd %s, %d(%s)\n", ppc_reg(0), 168+16+extra_stack_storage, ppc_reg(1)); + + /* Call the __wine_delay_load function, arg1 is arg1. */ + output( "\tlis %s, %s@highest\n", ppc_reg(12), asm_name("__wine_spec_delay_load") ); + output( "\tori %s, %s, %s@higher\n", ppc_reg(12), ppc_reg(12), asm_name("__wine_spec_delay_load") ); + output( "\trldicr %s, %s, 32, 31\n", ppc_reg(12), ppc_reg(12) ); + output( "\toris %s, %s, %s@high\n", ppc_reg(12), ppc_reg(12), asm_name("__wine_spec_delay_load") ); + output( "\tori %s, %s, %s@l\n", ppc_reg(12), ppc_reg(12), asm_name("__wine_spec_delay_load") ); + output( "\tmtctr %s\n", ppc_reg(12) ); + output( "\tbctrl\n" ); + + /* r3 (return value) -> r12 (branch / ctr) */ + output( "\tmr %s, %s\n", ppc_reg(12), ppc_reg(3)); + + /* Load return value from call into ctr register */ + output( "\tmtctr %s\n", ppc_reg(12)); + + /* restore all saved registers and drop stackframe. */ + output( "\tld %s, %d(%s)\n", ppc_reg(3), 48+extra_stack_storage, ppc_reg(1)); + output( "\tld %s, %d(%s)\n", ppc_reg(4), 56+extra_stack_storage, ppc_reg(1)); + output( "\tld %s, %d(%s)\n", ppc_reg(5), 64+extra_stack_storage, ppc_reg(1)); + output( "\tld %s, %d(%s)\n", ppc_reg(6), 72+extra_stack_storage, ppc_reg(1)); + output( "\tld %s, %d(%s)\n", ppc_reg(7), 80+extra_stack_storage, ppc_reg(1)); + output( "\tld %s, %d(%s)\n", ppc_reg(8), 88+extra_stack_storage, ppc_reg(1)); + output( "\tld %s, %d(%s)\n", ppc_reg(9), 96+extra_stack_storage, ppc_reg(1)); + output( "\tld %s, %d(%s)\n", ppc_reg(10),104+extra_stack_storage, ppc_reg(1)); + output( "\tld %s, %d(%s)\n", ppc_reg(11),112+extra_stack_storage, ppc_reg(1)); + /* don't restore r12! restoring r12 here would corrupt the computed TOC post-bctr. */ + + /* Load return value from call into return register */ + output( "\tld %s, %d(%s)\n", ppc_reg(0), 168+16+extra_stack_storage, ppc_reg(1)); + output( "\tmtlr %s\n", ppc_reg(0)); + output( "\tld %s, 0(%s)\n", ppc_reg(1), ppc_reg(1)); + /* branch to ctr register. */ output( "\tbctr\n"); break; @@ -1123,6 +1194,26 @@ static void output_delayed_import_thunks( const DLLSPEC *spec ) break; } break; + case CPU_POWERPC64: + /* Set up arg1 (r0) + * Clobbers r12 since ppc64 ABI v2 expects r12 == ctr at branch to ctr, + * i.e. we set up r12 right after this. + */ + output( "\tlis %s, %d@highest\n", ppc_reg(12), (idx << 16) | j ); + output( "\tori %s, %s, %d@higher\n", ppc_reg(12), ppc_reg(12), (idx << 16) | j ); + output( "\trldicr %s, %s, 32, 31\n", ppc_reg(12), ppc_reg(12) ); + output( "\toris %s, %s, %d@high\n", ppc_reg(12), ppc_reg(12), (idx << 16) | j ); + output( "\tori %s, %s, %d@l\n", ppc_reg(12), ppc_reg(12), (idx << 16) | j ); + output( "\tmr %s, %s\n", ppc_reg(0), ppc_reg(12) ); + + output( "\tlis %s, %s@highest\n", ppc_reg(12), asm_name("__wine_delay_load_asm") ); + output( "\tori %s, %s, %s@higher\n", ppc_reg(12), ppc_reg(12), asm_name("__wine_delay_load_asm") ); + output( "\trldicr %s, %s, 32, 31\n", ppc_reg(12), ppc_reg(12) ); + output( "\toris %s, %s, %s@high\n", ppc_reg(12), ppc_reg(12), asm_name("__wine_delay_load_asm") ); + output( "\tori %s, %s, %s@l\n", ppc_reg(12), ppc_reg(12), asm_name("__wine_delay_load_asm") ); + output( "\tmtctr %s\n", ppc_reg(12) ); + output( "\tbctr\n" ); + break; } output_cfi( ".cfi_endproc" ); } @@ -1297,6 +1388,32 @@ void output_stubs( DLLSPEC *spec ) output( "\tadd x2, x2, #:lo12:%s\n", asm_name("__wine_spec_unimplemented_stub") ); output( "\tblr x2\n" ); break; + case CPU_POWERPC64: + /* Clobbers r3, r4, and r12 */ + output( "\tlis %s, %s@highest\n", ppc_reg(3), asm_name("__wine_spec_file_name") ); + output( "\tori %s, %s, %s@higher\n", ppc_reg(3), ppc_reg(3), asm_name("__wine_spec_file_name") ); + output( "\trldicr %s, %s, 32, 31\n", ppc_reg(3), ppc_reg(3) ); + output( "\toris %s, %s, %s@high\n", ppc_reg(3), ppc_reg(3), asm_name("__wine_spec_file_name") ); + output( "\tori %s, %s, %s@l\n", ppc_reg(3), ppc_reg(3), asm_name("__wine_spec_file_name") ); + if (exp_name) + { + output( "\tlis %s, .L%s_string@highest\n", ppc_reg(4), name ); + output( "\tori %s, %s, .L%s_string@higher\n", ppc_reg(4), ppc_reg(4), name ); + output( "\trldicr %s, %s, 32, 31\n", ppc_reg(4), ppc_reg(4) ); + output( "\toris %s, %s, .L%s_string@high\n", ppc_reg(4), ppc_reg(4), name ); + output( "\tori %s, %s, .L%s_string@l\n", ppc_reg(4), ppc_reg(4), name ); + count++; + } + else + { + output( "\tlis %s, %u@highest\n", ppc_reg(4), odp->ordinal ); + output( "\tori %s, %s, %u@higher\n", ppc_reg(4), ppc_reg(4), odp->ordinal ); + output( "\trldicr %s, %s, 32, 31\n", ppc_reg(4), ppc_reg(4) ); + output( "\toris %s, %s, %u@high\n", ppc_reg(4), ppc_reg(4), odp->ordinal ); + output( "\tori %s, %s, %u@l\n", ppc_reg(4), ppc_reg(4), odp->ordinal ); + } + output( "\tbl %s\n", asm_name("__wine_spec_unimplemented_stub") ); + break; default: assert(0); } diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index b2f5c959c4..406679f2c8 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -51,6 +51,8 @@ int unwind_tables = 0; enum target_cpu target_cpu = CPU_x86; #elif defined(__x86_64__) enum target_cpu target_cpu = CPU_x86_64; +#elif defined(__powerpc64__) +enum target_cpu target_cpu = CPU_POWERPC64; #elif defined(__powerpc__) enum target_cpu target_cpu = CPU_POWERPC; #elif defined(__arm__) @@ -552,6 +554,10 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec ) case CPU_x86_64: if (force_pointer_size == 4) target_cpu = CPU_x86; break; + case CPU_POWERPC64: + if (force_pointer_size == 4) + fatal_error( "Cannot build 32-bit code for this CPU\n" ); + break; default: if (force_pointer_size == 8) fatal_error( "Cannot build 64-bit code for this CPU\n" ); diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c index ad996547a5..f59ac7302a 100644 --- a/tools/winebuild/parser.c +++ b/tools/winebuild/parser.c @@ -403,9 +403,9 @@ static int parse_spec_stub( ORDDEF *odp, DLLSPEC *spec ) odp->link_name = xstrdup(""); /* don't bother generating stubs for Winelib */ if (odp->flags & FLAG_CPU_MASK) - odp->flags &= FLAG_CPU(CPU_x86) | FLAG_CPU(CPU_x86_64) | FLAG_CPU(CPU_ARM) | FLAG_CPU(CPU_ARM64); + odp->flags &= FLAG_CPU(CPU_x86) | FLAG_CPU(CPU_x86_64) | FLAG_CPU(CPU_ARM) | FLAG_CPU(CPU_ARM64) | FLAG_CPU(CPU_POWERPC64); else - odp->flags |= FLAG_CPU(CPU_x86) | FLAG_CPU(CPU_x86_64) | FLAG_CPU(CPU_ARM) | FLAG_CPU(CPU_ARM64); + odp->flags |= FLAG_CPU(CPU_x86) | FLAG_CPU(CPU_x86_64) | FLAG_CPU(CPU_ARM) | FLAG_CPU(CPU_ARM64) | FLAG_CPU(CPU_POWERPC64);
return parse_spec_arguments( odp, spec, 1 ); } diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index 3552eca74f..e57552552b 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -32,12 +32,13 @@
#include "build.h"
-#define IMAGE_FILE_MACHINE_UNKNOWN 0 -#define IMAGE_FILE_MACHINE_I386 0x014c -#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 -#define IMAGE_FILE_MACHINE_AMD64 0x8664 -#define IMAGE_FILE_MACHINE_ARMNT 0x01C4 -#define IMAGE_FILE_MACHINE_ARM64 0xaa64 +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 +#define IMAGE_FILE_MACHINE_POWERPC64 0x01f2 +#define IMAGE_FILE_MACHINE_AMD64 0x8664 +#define IMAGE_FILE_MACHINE_ARMNT 0x01C4 +#define IMAGE_FILE_MACHINE_ARM64 0xaa64
#define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224 #define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240 @@ -515,6 +516,7 @@ static void output_asm_constructor( const char *constructor ) break; case CPU_ARM64: case CPU_POWERPC: + case CPU_POWERPC64: output( "\n\t.section ".init","ax"\n" ); output( "\tbl %s\n", asm_name(constructor) ); break; @@ -562,6 +564,7 @@ void output_module( DLLSPEC *spec ) break; case CPU_ARM64: case CPU_POWERPC: + case CPU_POWERPC64: output( "\n\t.section ".init","ax"\n" ); output( "\tb 1f\n" ); break; @@ -582,11 +585,12 @@ void output_module( DLLSPEC *spec ) output( "\t.long 0x4550\n" ); /* Signature */ switch(target_cpu) { - case CPU_x86: machine = IMAGE_FILE_MACHINE_I386; break; - case CPU_x86_64: machine = IMAGE_FILE_MACHINE_AMD64; break; - case CPU_POWERPC: machine = IMAGE_FILE_MACHINE_POWERPC; break; - case CPU_ARM: machine = IMAGE_FILE_MACHINE_ARMNT; break; - case CPU_ARM64: machine = IMAGE_FILE_MACHINE_ARM64; break; + case CPU_x86: machine = IMAGE_FILE_MACHINE_I386; break; + case CPU_x86_64: machine = IMAGE_FILE_MACHINE_AMD64; break; + case CPU_POWERPC: machine = IMAGE_FILE_MACHINE_POWERPC; break; + case CPU_POWERPC64: machine = IMAGE_FILE_MACHINE_POWERPC64; break; + case CPU_ARM: machine = IMAGE_FILE_MACHINE_ARMNT; break; + case CPU_ARM64: machine = IMAGE_FILE_MACHINE_ARM64; break; } output( "\t.short 0x%04x\n", /* Machine */ machine ); @@ -765,11 +769,12 @@ void output_fake_module( DLLSPEC *spec ) put_dword( 0x4550 ); /* Signature */ switch(target_cpu) { - case CPU_x86: put_word( IMAGE_FILE_MACHINE_I386 ); break; - case CPU_x86_64: put_word( IMAGE_FILE_MACHINE_AMD64 ); break; - case CPU_POWERPC: put_word( IMAGE_FILE_MACHINE_POWERPC ); break; - case CPU_ARM: put_word( IMAGE_FILE_MACHINE_ARMNT ); break; - case CPU_ARM64: put_word( IMAGE_FILE_MACHINE_ARM64 ); break; + case CPU_x86: put_word( IMAGE_FILE_MACHINE_I386 ); break; + case CPU_x86_64: put_word( IMAGE_FILE_MACHINE_AMD64 ); break; + case CPU_POWERPC: put_word( IMAGE_FILE_MACHINE_POWERPC ); break; + case CPU_POWERPC64: put_word( IMAGE_FILE_MACHINE_POWERPC64 ); break; + case CPU_ARM: put_word( IMAGE_FILE_MACHINE_ARMNT ); break; + case CPU_ARM64: put_word( IMAGE_FILE_MACHINE_ARM64 ); break; } put_word( nb_sections ); /* NumberOfSections */ put_dword( 0 ); /* TimeDateStamp */ diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c index 78e9645411..7b068d32b0 100644 --- a/tools/winebuild/utils.c +++ b/tools/winebuild/utils.c @@ -62,6 +62,7 @@ static const struct { "amd64", CPU_x86_64 }, { "x86_64", CPU_x86_64 }, { "powerpc", CPU_POWERPC }, + { "powerpc64", CPU_POWERPC64 }, { "arm", CPU_ARM }, { "armv5", CPU_ARM }, { "armv6", CPU_ARM }, @@ -410,6 +411,7 @@ struct strarray get_as_command(void) default: switch(target_cpu) { + case CPU_POWERPC64: case CPU_POWERPC: strarray_add_one( &args, (force_pointer_size == 8) ? "-a64" : "-a32" ); break; @@ -451,6 +453,13 @@ struct strarray get_ld_command(void) default: switch(target_cpu) { + case CPU_POWERPC64: +#if defined(__BIG_ENDIAN__) + strarray_add( &args, "-m", (force_pointer_size == 8) ? "elf64ppc" : "elf32ppc", NULL ); +#else + strarray_add( &args, "-m", (force_pointer_size == 8) ? "elf64lppc" : "elf32lppc", NULL ); +#endif + break; case CPU_POWERPC: strarray_add( &args, "-m", (force_pointer_size == 8) ? "elf64ppc" : "elf32ppc", NULL ); break; @@ -897,6 +906,7 @@ unsigned int get_alignment(unsigned int align) if (target_platform != PLATFORM_APPLE) return align; /* fall through */ case CPU_POWERPC: + case CPU_POWERPC64: case CPU_ARM: case CPU_ARM64: n = 0; @@ -918,6 +928,7 @@ unsigned int get_page_size(void) case CPU_POWERPC: case CPU_ARM: return 0x1000; + case CPU_POWERPC64: case CPU_ARM64: return 0x10000; } @@ -937,6 +948,7 @@ unsigned int get_ptr_size(void) return 4; case CPU_x86_64: case CPU_ARM64: + case CPU_POWERPC64: return 8; } /* unreached */ diff --git a/tools/winedump/minidump.c b/tools/winedump/minidump.c index da1369cbf8..c2767033c7 100644 --- a/tools/winedump/minidump.c +++ b/tools/winedump/minidump.c @@ -284,6 +284,9 @@ void mdmp_dump(void) case PROCESSOR_ARCHITECTURE_PPC: str = "PowerPC"; break; + case PROCESSOR_ARCHITECTURE_PPC64: + str = "PowerPC 64"; + break; case PROCESSOR_ARCHITECTURE_ARM: str = "ARM"; break; diff --git a/tools/winedump/pe.c b/tools/winedump/pe.c index f8689f7f33..3721db67a7 100644 --- a/tools/winedump/pe.c +++ b/tools/winedump/pe.c @@ -59,6 +59,7 @@ const char *get_machine_str(int mach) case IMAGE_FILE_MACHINE_R10000: return "R10000"; case IMAGE_FILE_MACHINE_ALPHA: return "Alpha"; case IMAGE_FILE_MACHINE_POWERPC: return "PowerPC"; + case IMAGE_FILE_MACHINE_POWERPC64: return "PowerPC64"; case IMAGE_FILE_MACHINE_AMD64: return "AMD64"; case IMAGE_FILE_MACHINE_IA64: return "IA64"; case IMAGE_FILE_MACHINE_ARM64: return "ARM64"; diff --git a/tools/winegcc/utils.h b/tools/winegcc/utils.h index 536fb2d2f9..e83b6b743d 100644 --- a/tools/winegcc/utils.h +++ b/tools/winegcc/utils.h @@ -37,7 +37,7 @@
enum target_cpu { - CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64 + CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64, CPU_POWERPC64 };
enum target_platform diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index 54d43685df..cc5738c370 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -160,6 +160,7 @@ static const struct { "amd64", CPU_x86_64 }, { "x86_64", CPU_x86_64 }, { "powerpc", CPU_POWERPC }, + { "powerpc64", CPU_POWERPC64 }, { "arm", CPU_ARM }, { "armv5", CPU_ARM }, { "armv6", CPU_ARM }, @@ -225,6 +226,8 @@ struct options static const enum target_cpu build_cpu = CPU_x86; #elif defined(__x86_64__) static const enum target_cpu build_cpu = CPU_x86_64; +#elif defined(__powerpc64__) +static const enum target_cpu build_cpu = CPU_POWERPC64; #elif defined(__powerpc__) static const enum target_cpu build_cpu = CPU_POWERPC; #elif defined(__arm__) @@ -436,9 +439,9 @@ static int check_platform( struct options *opts, const char *file ) if (!memcmp( header, "\177ELF", 4 )) { if (header[4] == 2) /* 64-bit */ - ret = (opts->target_cpu == CPU_x86_64 || opts->target_cpu == CPU_ARM64); + ret = (opts->target_cpu == CPU_x86_64 || opts->target_cpu == CPU_ARM64 || opts->target_cpu == CPU_POWERPC64); else - ret = (opts->target_cpu != CPU_x86_64 && opts->target_cpu != CPU_ARM64); + ret = (opts->target_cpu != CPU_x86_64 && opts->target_cpu != CPU_ARM64 && opts->target_cpu != CPU_POWERPC64); } } close( fd ); @@ -450,11 +453,12 @@ static const char *get_multiarch_dir( enum target_cpu cpu ) { switch(cpu) { - case CPU_x86: return "/i386-linux-gnu"; - case CPU_x86_64: return "/x86_64-linux-gnu"; - case CPU_ARM: return "/arm-linux-gnueabi"; - case CPU_ARM64: return "/aarch64-linux-gnu"; - case CPU_POWERPC: return "/powerpc-linux-gnu"; + case CPU_x86: return "/i386-linux-gnu"; + case CPU_x86_64: return "/x86_64-linux-gnu"; + case CPU_ARM: return "/arm-linux-gnueabi"; + case CPU_ARM64: return "/aarch64-linux-gnu"; + case CPU_POWERPC: return "/powerpc-linux-gnu"; + case CPU_POWERPC64: return "/powerpc64le-linux-gnu"; default: assert(0); return NULL; @@ -469,8 +473,8 @@ static char *get_lib_dir( struct options *opts ) unsigned int i; size_t build_len, target_len;
- bit_suffix = opts->target_cpu == CPU_x86_64 || opts->target_cpu == CPU_ARM64 ? "64" : "32"; - other_bit_suffix = opts->target_cpu == CPU_x86_64 || opts->target_cpu == CPU_ARM64 ? "32" : "64"; + bit_suffix = opts->target_cpu == CPU_x86_64 || opts->target_cpu == CPU_ARM64 || opts->target_cpu == CPU_POWERPC64 ? "64" : "32"; + other_bit_suffix = opts->target_cpu == CPU_x86_64 || opts->target_cpu == CPU_ARM64 || opts->target_cpu == CPU_POWERPC64 ? "32" : "64"; build_multiarch = get_multiarch_dir( build_cpu ); target_multiarch = get_multiarch_dir( opts->target_cpu ); build_len = strlen( build_multiarch ); @@ -595,7 +599,7 @@ static void compile(struct options* opts, const char* lang) strarray_add(comp_args, "-fPIC"); }
- if (opts->target_cpu == CPU_x86_64 || opts->target_cpu == CPU_ARM64) + if (opts->target_cpu == CPU_x86_64 || opts->target_cpu == CPU_ARM64 || opts->target_cpu == CPU_POWERPC64) { strarray_add(comp_args, "-DWIN64"); strarray_add(comp_args, "-D_WIN64"); @@ -633,6 +637,7 @@ static void compile(struct options* opts, const char* lang) case CPU_ARM: case CPU_ARM64: case CPU_POWERPC: + case CPU_POWERPC64: strarray_add(comp_args, "-D__stdcall="); strarray_add(comp_args, "-D__cdecl="); strarray_add(comp_args, "-D_stdcall="); @@ -659,7 +664,7 @@ static void compile(struct options* opts, const char* lang) strarray_add(comp_args, "-D__int8=char"); strarray_add(comp_args, "-D__int16=short"); strarray_add(comp_args, "-D__int32=int"); - if (opts->target_cpu == CPU_x86_64 || opts->target_cpu == CPU_ARM64) + if (opts->target_cpu == CPU_x86_64 || opts->target_cpu == CPU_ARM64 || opts->target_cpu == CPU_POWERPC64) strarray_add(comp_args, "-D__int64=long"); else strarray_add(comp_args, "-D__int64=long long"); @@ -1216,8 +1221,14 @@ static void build(struct options* opts) else prelink = PRELINK; } - if (!try_link(opts->prefix, link_args, "-Wl,-z,max-page-size=0x1000")) - strarray_add(link_args, "-Wl,-z,max-page-size=0x1000"); + if (opts->target_cpu == CPU_POWERPC64) { + if (!try_link(opts->prefix, link_args, "-Wl,-z,max-page-size=0x10000")) + strarray_add(link_args, "-Wl,-z,max-page-size=0x10000"); + } + else { + if (!try_link(opts->prefix, link_args, "-Wl,-z,max-page-size=0x1000")) + strarray_add(link_args, "-Wl,-z,max-page-size=0x1000"); + } break; }
@@ -1588,6 +1599,8 @@ int main(int argc, char **argv) opts.target_cpu = CPU_x86; else if (opts.target_cpu == CPU_ARM64) opts.target_cpu = CPU_ARM; + else if (opts.target_cpu == CPU_POWERPC64) + opts.target_cpu = CPU_POWERPC; opts.force_pointer_size = 4; raw_linker_arg = 1; } @@ -1597,6 +1610,8 @@ int main(int argc, char **argv) opts.target_cpu = CPU_x86_64; else if (opts.target_cpu == CPU_ARM) opts.target_cpu = CPU_ARM64; + else if (opts.target_cpu == CPU_POWERPC) + opts.target_cpu = CPU_POWERPC64; opts.force_pointer_size = 8; raw_linker_arg = 1; } diff --git a/tools/wrc/wrc.c b/tools/wrc/wrc.c index ea8bfe07a7..f05d687eb0 100644 --- a/tools/wrc/wrc.c +++ b/tools/wrc/wrc.c @@ -317,7 +317,8 @@ static void set_target( const char *target ) if (!(p = strchr( cpu, '-' ))) error( "Invalid target specification '%s'\n", target ); *p = 0; if (!strcmp( cpu, "amd64" ) || !strcmp( cpu, "x86_64" ) || - !strcmp( cpu, "ia64" ) || !strcmp( cpu, "aarch64" )) + !strcmp( cpu, "ia64" ) || !strcmp( cpu, "aarch64" ) || + !strcmp( cpu, "ppc64" ) || strcmp( cpu, "ppc64el" ) || strcmp( cpu, "ppc64le" )) pointer_size = 8; else pointer_size = 4;
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=48265
Your paranoid android.
=== debian9 (32 bit WoW report) ===
ntdll: pipe.c:1557: Test failed: pipe is not signaled pipe.c:1576: Test failed: pipe is not signaled
=== debian9 (64 bit WoW report) ===
ntdll: pipe.c:1557: Test failed: pipe is not signaled
Hi,
Some notes on this patch: * Please split it, see my ARM or even better my ARM64 patches for it: [1], especially [2] (6 years ago, WHAT???) * git complains about white-space issues when applying, those need to be fixed * I needed to add support in the wine tools for powerpc64le, because my toolchain was named that way * I had a quick try with qemu user space emulation and directly ran into the assertion in signal_ppc64.c:signal_alloc_thread(): assert( sizeof(TEB) <= min_size ); * A very minor one: For easier searching for commits a constant platform naming helps, I tried to include "ARM64" in all related patch subjects, maybe PPC64 fits here well
[1] https://source.winehq.org/git/wine.git/?a=search&h=HEAD&st=commit&am... [2] https://source.winehq.org/git/wine.git/shortlog/fcc204c989928e4304f3b93a7bbc...
Am 26.02.19 um 11:04 schrieb Timothy Pearson:
to start winecfg
Signed-off-by: Timothy Pearson tpearson@raptorengineering.com
configure | 38 + configure.ac | 9 + dlls/dbghelp/Makefile.in | 1 + dlls/dbghelp/cpu_ppc64.c | 100 +++ dlls/dbghelp/dbghelp.c | 6 +- dlls/kernel32/cpu.c | 3 + dlls/kernel32/module.c | 1 + dlls/kernel32/process.c | 8 +- dlls/kernel32/tests/file.c | 2 + dlls/kernel32/tests/loader.c | 2 + dlls/kernel32/tests/module.c | 2 + dlls/ntdll/Makefile.in | 1 + dlls/ntdll/loader.c | 10 +- dlls/ntdll/nt.c | 8 + dlls/ntdll/ntdll.spec | 2 +- dlls/ntdll/process.c | 8 +- dlls/ntdll/server.c | 6 +- dlls/ntdll/signal_powerpc.c | 4 +- dlls/ntdll/signal_ppc64.c | 1221 +++++++++++++++++++++++++++++++ dlls/ntdll/virtual.c | 2 +- dlls/setupapi/fakedll.c | 2 + dlls/ucrtbase/ucrtbase.spec | 2 +- include/basetsd.h | 10 + include/msvcrt/crtdefs.h | 6 + include/rpc.h | 4 +- include/windef.h | 6 + include/wine/server_protocol.h | 6 +- include/winnt.h | 138 +++- libs/port/interlocked.c | 2 +- libs/wine/port.c | 19 + programs/winedbg/Makefile.in | 1 + programs/winedbg/be_ppc.c | 2 +- programs/winedbg/be_ppc64.c | 303 ++++++++ programs/winedbg/gdbproxy.c | 2 + programs/winedbg/tgt_active.c | 2 + programs/winedbg/tgt_minidump.c | 3 + programs/winedbg/winedbg.c | 4 + programs/winetest/main.c | 2 + server/mapping.c | 8 +- server/process.h | 2 +- server/protocol.def | 6 +- server/thread.c | 6 + server/trace.c | 21 + tools/widl/widl.c | 7 + tools/widl/widl.h | 2 +- tools/widl/write_msft.c | 2 +- tools/winebuild/build.h | 4 +- tools/winebuild/import.c | 117 +++ tools/winebuild/main.c | 6 + tools/winebuild/parser.c | 4 +- tools/winebuild/spec32.c | 37 +- tools/winebuild/utils.c | 12 + tools/winedump/minidump.c | 3 + tools/winedump/pe.c | 1 + tools/winegcc/utils.h | 2 +- tools/winegcc/winegcc.c | 41 +- tools/wrc/wrc.c | 3 +- 57 files changed, 2168 insertions(+), 64 deletions(-) create mode 100644 dlls/dbghelp/cpu_ppc64.c create mode 100644 dlls/ntdll/signal_ppc64.c create mode 100644 programs/winedbg/be_ppc64.c
From: "André Hentschel" nerv@dawncrow.de To: "Timothy Pearson" tpearson@raptorengineering.com, "wine-devel" wine-devel@winehq.org Sent: Tuesday, February 26, 2019 12:48:33 PM Subject: Re: [PATCH 2/3] Initial port to PowerPC 64 Little Endian systems Verified
Hi,
Some notes on this patch:
- Please split it, see my ARM or even better my ARM64 patches for it: [1],
especially [2] (6 years ago, WHAT???)
- git complains about white-space issues when applying, those need to be fixed
- I needed to add support in the wine tools for powerpc64le, because my
toolchain was named that way
- I had a quick try with qemu user space emulation and directly ran into the
assertion in signal_ppc64.c:signal_alloc_thread(): assert( sizeof(TEB) <= min_size );
- A very minor one: For easier searching for commits a constant platform naming
helps, I tried to include "ARM64" in all related patch subjects, maybe PPC64 fits here well
Thanks for the feedback and links. I'll start working on a v2.
What did you need to edit for powerpc64le? I can throw that in as another patch in the series.
qemu user space emulation is not great. My first guess would be page size -- most POWER systems use 64k pages, x86 machines only use 4k pages. I've run into similar problems the other way (trying to run x86 apps via user space emulation) on 64k POWER hosts. POWER does technically support 4k pages, but 4k kernels get a lot less testing and aren't the main focus here, at least initially. Higher priority is adding the missing exception handling code.
On 26.02.19 23:19, Timothy Pearson wrote:
From: "André Hentschel" nerv@dawncrow.de To: "Timothy Pearson" tpearson@raptorengineering.com, "wine-devel" wine-devel@winehq.org Sent: Tuesday, February 26, 2019 12:48:33 PM Subject: Re: [PATCH 2/3] Initial port to PowerPC 64 Little Endian systems Verified
Hi,
Some notes on this patch:
- Please split it, see my ARM or even better my ARM64 patches for it: [1],
especially [2] (6 years ago, WHAT???)
- git complains about white-space issues when applying, those need to be fixed
- I needed to add support in the wine tools for powerpc64le, because my
toolchain was named that way
- I had a quick try with qemu user space emulation and directly ran into the
assertion in signal_ppc64.c:signal_alloc_thread(): assert( sizeof(TEB) <= min_size );
- A very minor one: For easier searching for commits a constant platform naming
helps, I tried to include "ARM64" in all related patch subjects, maybe PPC64 fits here well
Thanks for the feedback and links. I'll start working on a v2.
What did you need to edit for powerpc64le? I can throw that in as another patch in the series.
Duplicating the detection line like this should be enough: { "powerpc64", CPU_POWERPC64 }, { "powerpc64le", CPU_POWERPC64 },