From: Toni Wilen Date: Fri, 29 Aug 2014 13:40:04 +0000 (+0300) Subject: QEMU PPC support. X-Git-Tag: 3000~74 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=f50f5f4e1f1f465e62904fdc5a8c8b966f20f4c1;p=francis%2Fwinuae.git QEMU PPC support. --- diff --git a/dlopen.cpp b/dlopen.cpp new file mode 100644 index 00000000..01a48e1a --- /dev/null +++ b/dlopen.cpp @@ -0,0 +1,55 @@ +#include "sysconfig.h" +#include "sysdeps.h" + +#include "uae/dlopen.h" +#ifdef _WIN32 + +#else +#include +#endif + +UAE_DLHANDLE uae_dlopen(const TCHAR *path) { +#ifdef _WIN32 + UAE_DLHANDLE result = LoadLibrary(path); +#else + UAE_DLHANDLE result = dlopen(path, RTLD_NOW); + const char *error = dlerror(); + if (error != NULL) { + write_log("uae_dlopen failed: %s\n", error); + } +#endif + return result; +} + +void *uae_dlsym(UAE_DLHANDLE handle, const char *name) +{ +#if 0 + if (handle == NULL) { + return NULL; + } +#endif +#ifdef _WIN32 + return (void *) GetProcAddress(handle, name); +#else + return dlsym(handle, name); +#endif +} + +void uae_dlclose(UAE_DLHANDLE handle) +{ +#ifdef _WIN32 + FreeLibrary (handle); +#else + dlclose(handle); +#endif +} + +#include "uae/log.h" + +void uae_patch_library_common(UAE_DLHANDLE handle) +{ + void *ptr; + + ptr = uae_dlsym(handle, "uae_log"); + if (ptr) *((uae_log_function *) ptr) = &uae_log; +} diff --git a/include/uae/api.h b/include/uae/api.h new file mode 100644 index 00000000..c72f35d8 --- /dev/null +++ b/include/uae/api.h @@ -0,0 +1,55 @@ +/* + * Helpers used to export UAE functions for use with other modules + * Copyright (C) 2014 Frode Solheim + * + * Licensed under the terms of the GNU General Public License version 2. + * See the file 'COPYING' for full license text. + */ + +#ifndef UAE_API_H +#define UAE_API_H + +/* This file is intended to be included by external libraries as well, + * so don't pull in too much UAE-specific stuff. */ + +#include "uae/attributes.h" + +/* Handy define so we can disable C++ name mangling without considering + * whether the source language is C or C++. */ + +#ifdef __cplusplus +#define UAE_EXTERN_C extern "C" +#else +#define UAE_EXTERN_C +#endif + +/* UAE_EXPORT / UAE_IMPORT are mainly intended as helpers for UAEAPI + * defined below. */ + +#ifdef _WIN32 +#define UAE_EXPORT __declspec(dllexport) +#define UAE_IMPORT __declspec(dllimport) +#else +#define UAE_EXPORT __attribute__((visibility("default"))) +#define UAE_IMPORT +#endif + +/* UAEAPI marks a function for export across library boundaries. You'll + * likely want to use this together with UAECALL. */ + +#ifdef UAE +#define UAEAPI UAE_EXTERN_C UAE_EXPORT +#else +#define UAEAPI UAE_EXTERN_C UAE_IMPORT +#endif + +/* WinUAE (or external libs) might be compiled with fastcall by default, + * so we force all external functions to use cdecl calling convention. */ + +#ifdef _WIN32 +#define UAECALL __cdecl +#else +#define UAECALL +#endif + +#endif /* UAE_API_H */ diff --git a/include/uae/attributes.h b/include/uae/attributes.h new file mode 100644 index 00000000..ec768df0 --- /dev/null +++ b/include/uae/attributes.h @@ -0,0 +1,24 @@ +/* + * Defines useful functions and variable attributes for UAE + * Copyright (C) 2014 Frode Solheim + * + * Licensed under the terms of the GNU General Public License version 2. + * See the file 'COPYING' for full license text. + */ + +#ifndef UAE_ATTRIBUTES_H +#define UAE_ATTRIBUTES_H + +/* This file is intended to be included by external libraries as well, + * so don't pull in too much UAE-specific stuff. */ + +/* This attribute allows (some) compiles to emit warnings when incorrect + * arguments are used with the format string. */ + +#ifdef __GNUC__ +#define UAE_PRINTF_FORMAT(f, a) __attribute__((format(printf, f, a))) +#else +#define UAE_PRINTF_FORMAT(f, a) +#endif + +#endif /* UAE_ATTRIBUTES_H */ diff --git a/include/uae/dlopen.h b/include/uae/dlopen.h new file mode 100644 index 00000000..2bc818ed --- /dev/null +++ b/include/uae/dlopen.h @@ -0,0 +1,26 @@ +/* + * Platform-independent loadable module functions for UAE. + * Copyright (C) 2014 Frode Solheim + * + * Licensed under the terms of the GNU General Public License version 2. + * See the file 'COPYING' for full license text. + */ + +#ifndef UAE_DLOPEN_H +#define UAE_DLOPEN_H + +#include "uae/types.h" + +#ifdef _WIN32 +#define UAE_DLHANDLE HINSTANCE +#else +#define UAE_DLHANDLE void * +#endif + +UAE_DLHANDLE uae_dlopen(const TCHAR *path); +void *uae_dlsym(UAE_DLHANDLE handle, const char *symbol); +void uae_dlclose(UAE_DLHANDLE handle); + +void uae_patch_library_common(UAE_DLHANDLE handle); + +#endif /* UAE_DLOPEN_H */ diff --git a/include/uae/log.h b/include/uae/log.h new file mode 100644 index 00000000..385942b8 --- /dev/null +++ b/include/uae/log.h @@ -0,0 +1,94 @@ +/* + * Logging functions for use with UAE and external modules + * Copyright (C) 2014 Frode Solheim + * + * Licensed under the terms of the GNU General Public License version 2. + * See the file 'COPYING' for full license text. + */ + +#ifndef UAE_LOGGING_H +#define UAE_LOGGING_H + +/* This file is intended to be included by external libraries as well, + * so don't pull in too much UAE-specific stuff. */ + +#include "uae/api.h" +#include "uae/attributes.h" +#include "uae/types.h" + +typedef void (UAECALL *uae_log_function)(const char *format, ...) UAE_PRINTF_FORMAT(1, 2); +#ifdef UAE +//UAEAPI void UAECALL uae_log(const char *format, ...) UAE_PRINTF_FORMAT(1, 2); +void UAECALL uae_log(const char *format, ...) UAE_PRINTF_FORMAT(1, 2); +#else +extern uae_log_function uae_log; +#endif + +#if 0 +void uae_warning(const char *format, ...) UAE_PRINTF_FORMAT(1, 2); +void uae_error(const char *format, ...) UAE_PRINTF_FORMAT(1, 2); +void uae_fatal(const char *format, ...) UAE_PRINTF_FORMAT(1, 2); +#endif + +#define UAE_LOG_VA_ARGS(format, ap) \ +{ \ + char buffer[1024]; \ + vsnprintf(buffer, 1024, format, ap); \ + uae_log("%s", buffer); \ +} + +#define UAE_LOG_VA_ARGS_FULL(format) \ +{ \ + va_list ap; \ + va_start(ap, format); \ + UAE_LOG_VA_ARGS(format, ap); \ + va_end(ap); \ +} + +/* Helpers to log use of stubbed functions */ + +#define UAE_LOG_STUB(format, ...) \ +{ \ + uae_log(" -- stub -- %s " format "\n", __func__, ##__VA_ARGS__); \ +} + +#define UAE_LOG_STUB_MAX(max, format, ...) \ +{ \ + static int log_stub_count = 0; \ + if (log_stub_count < max) { \ + LOG_STUB(format, ##__VA_ARGS__) \ + if (++log_stub_count == max) { \ + uae_log(" (ignoring further calls to %s)\n", __func__); \ + } \ + } \ +} + +#define UAE_STUB(format, ...) \ +{ \ + UAE_LOG_STUB(format, ##__VA_ARGS__) \ + printf(" -- stub -- %s " format "\n", __func__, ##__VA_ARGS__); \ +} + +/* UAE-specific functions */ + +#ifdef UAE + +void write_log (const char *, ...) UAE_PRINTF_FORMAT(1, 2); +#if SIZEOF_TCHAR != 1 +void write_log (const TCHAR *, ...) UAE_PRINTF_FORMAT(1, 2); +#endif + +#endif + +/* Deprecated defines */ + +#ifdef UAE + +#define STUB UAE_STUB +#define LOG_STUB UAE_LOG_STUB +#define LOG_STUB_MAX UAE_LOG_STUB_MAX +#define VERBOSE_STUB STUB + +#endif + +#endif /* UAE_LOGGING_H */ diff --git a/include/uae/ppc.h b/include/uae/ppc.h new file mode 100644 index 00000000..f95045e7 --- /dev/null +++ b/include/uae/ppc.h @@ -0,0 +1,102 @@ +/* + * Platform-independent loadable module functions for UAE + * Copyright (C) 2014 Toni Wilen, Frode Solheim + * + * Licensed under the terms of the GNU General Public License version 2. + * See the file 'COPYING' for full license text. + */ + +#ifndef UAE_PPC_H +#define UAE_PPC_H + +/* This file is intended to be included by external libraries as well, + * so don't pull in too much UAE-specific stuff. */ + +#include "uae/api.h" +#include "uae/types.h" + +#ifdef UAE +#define PPCAPI UAE_EXTERN_C UAE_IMPORT +#else +#define PPCAPI UAE_EXTERN_C UAE_EXPORT +#endif +#define PPCCALL UAECALL + +/* UAE PPC functions and variables only visible to UAE */ + +#ifdef UAE + +void uae_ppc_doze(void); +void uae_ppc_sync (void); +void uae_ppc_crash(void); +void uae_ppc_cpu_reboot(void); +void uae_ppc_cpu_stop(void); +bool uae_ppc_poll_queue(void); +void uae_ppc_interrupt(bool active); +void uae_ppc_cpu_lock(void); +bool uae_ppc_cpu_unlock(void); +void uae_ppc_to_main_thread(void); +void uae_ppc_emulate(void); +void uae_ppc_reset(bool hardreset); +void uae_ppc_hsync_handler(void); +void uae_ppc_wakeup(void); + +#ifdef __cplusplus +bool uae_ppc_direct_physical_memory_handle(uint32_t addr, uint8_t *&ptr); +#endif + +extern volatile int ppc_state; +extern int ppc_cycle_count; + +#endif /* UAE */ + +/* Exported UAE functions which external PPC implementations can use */ + +typedef bool (UAECALL *uae_ppc_io_mem_read_function)(uint32_t addr, uint32_t *data, int size); +typedef bool (UAECALL *uae_ppc_io_mem_write_function)(uint32_t addr, uint32_t data, int size); +typedef bool (UAECALL *uae_ppc_io_mem_read64_function)(uint32_t addr, uint64_t *data); +typedef bool (UAECALL *uae_ppc_io_mem_write64_function)(uint32_t addr, uint64_t data); + +#ifdef UAE + +bool UAECALL uae_ppc_io_mem_read(uint32_t addr, uint32_t *data, int size); +bool UAECALL uae_ppc_io_mem_write(uint32_t addr, uint32_t data, int size); +bool UAECALL uae_ppc_io_mem_read64(uint32_t addr, uint64_t *data); +bool UAECALL uae_ppc_io_mem_write64(uint32_t addr, uint64_t data); + +#else + +extern uae_ppc_io_mem_read_function uae_ppc_io_mem_read; +extern uae_ppc_io_mem_write_function uae_ppc_io_mem_write; +extern uae_ppc_io_mem_read64_function uae_ppc_io_mem_read64; +extern uae_ppc_io_mem_write64_function uae_ppc_io_mem_write64; + +#endif + +/* Prototypes for PPC CPU implementation, used by PearPC and QEmu */ + +bool PPCCALL ppc_cpu_init(uint32_t pvr); +void PPCCALL ppc_cpu_free(void); +void PPCCALL ppc_cpu_stop(void); +void PPCCALL ppc_cpu_atomic_raise_ext_exception(void); +void PPCCALL ppc_cpu_atomic_cancel_ext_exception(void); +void PPCCALL ppc_cpu_map_memory(uint32_t addr, uint32_t size, void *memory, const char *name); +void PPCCALL ppc_cpu_set_pc(int cpu, uint32_t value); +void PPCCALL ppc_cpu_run_continuous(void); +void PPCCALL ppc_cpu_run_single(int count); +uint64_t PPCCALL ppc_cpu_get_dec(void); +void PPCCALL ppc_cpu_do_dec(int value); + +/* Other PPC defines */ + +#define PPC_IMPLEMENTATION_AUTO 0 +#define PPC_IMPLEMENTATION_DUMMY 1 +#define PPC_IMPLEMENTATION_PEARPC 2 +#define PPC_IMPLEMENTATION_QEMU 3 + +#define PPC_STATE_STOP 0 +#define PPC_STATE_ACTIVE 1 +#define PPC_STATE_SLEEP 2 +#define PPC_STATE_CRASH 3 + +#endif /* UAE_PPC_H */ diff --git a/include/uae/types.h b/include/uae/types.h new file mode 100644 index 00000000..5cb7448d --- /dev/null +++ b/include/uae/types.h @@ -0,0 +1,91 @@ +/* + * Common types used throughout the UAE source code + * Copyright (C) 2014 Frode Solheim + * + * Licensed under the terms of the GNU General Public License version 2. + * See the file 'COPYING' for full license text. + */ + +#ifndef UAE_TYPES_H +#define UAE_TYPES_H + +/* This file is intended to be included by external libraries as well, + * so don't pull in too much UAE-specific stuff. */ + +#if 0 +#include "config.h" +#endif + +/* Define uae_ integer types. Prefer long long int for uae_x64 since we can + * then use the %lld format specifier for both 32-bit and 64-bit instead of + * the ugly PRIx64 macros. */ + +#include + +typedef int8_t uae_s8; +typedef uint8_t uae_u8; + +typedef int16_t uae_s16; +typedef uint16_t uae_u16; + +typedef int32_t uae_s32; +typedef uint32_t uae_u32; + +#ifndef uae_s64 +typedef long long int uae_s64; +#endif + +#ifndef uae_u64 +typedef unsigned long long int uae_u64; +#endif + +/* Parts of the UAE/WinUAE code uses the bool type (from C++). + * Including stdbool.h lets this be valid also when compiling with C. */ + +#ifndef __cplusplus +#include +#endif + +/* Use uaecptr to represent 32-bit (or 24-bit) addresses into the Amiga + * address space. This is a 32-bit unsigned int regarless of host arch. */ + +typedef uae_u32 uaecptr; + +/* Define UAE character types. WinUAE uses TCHAR (typedef for wchar_t) for + * many strings. FS-UAE always uses char-based strings in UTF-8 format. + * Defining SIZEOF_TCHAR lets us determine whether to include overloaded + * functions in some cases or not. */ + +typedef char uae_char; + +#ifdef _WIN32 +#include +#ifdef UNICODE +#define SIZEOF_TCHAR 2 +#else +#define SIZEOF_TCHAR 1 +#endif +#else +typedef char TCHAR; +#define SIZEOF_TCHAR 1 +#endif + +#ifndef _T +#if SIZEOF_TCHAR == 1 +#define _T(x) x +#else +#define _T(x) Lx +#endif +#endif + +#ifndef BOOL +#define BOOL int +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#endif /* UAE_TYPES_H */ diff --git a/logging.cpp b/logging.cpp new file mode 100644 index 00000000..b3b14864 --- /dev/null +++ b/logging.cpp @@ -0,0 +1,14 @@ +#include "uae/log.h" +#include +#include + +//UAEAPI void UAECALL uae_log(const char *format, ...) +void UAECALL uae_log(const char *format, ...) +{ + char buffer[1000]; + va_list ap; + va_start(ap, format); + vsnprintf(buffer, 1000, format, ap); + write_log("%s", buffer); + va_end(ap); +} diff --git a/ppc/pearpc/cpu/cpu.h b/ppc/pearpc/cpu/cpu.h index 64d0053e..dffca565 100644 --- a/ppc/pearpc/cpu/cpu.h +++ b/ppc/pearpc/cpu/cpu.h @@ -22,16 +22,17 @@ #define __CPU_H__ #include "system/types.h" +#include "uae/ppc.h" uint64 ppc_get_clock_frequency(int cpu); uint64 ppc_get_bus_frequency(int cpu); uint64 ppc_get_timebase_frequency(int cpu); -bool ppc_cpu_init(uint32); +bool PPCCALL ppc_cpu_init(uint32); void ppc_cpu_init_config(); -void ppc_cpu_free(void); +void PPCCALL ppc_cpu_free(void); -void ppc_cpu_stop(); +void PPCCALL ppc_cpu_stop(); void ppc_cpu_wakeup(); void ppc_machine_check_exception(); @@ -43,12 +44,12 @@ void ppc_cpu_cancel_ext_exception(); * May only be called from within a CPU thread. */ -void ppc_cpu_run_continuous(); -void ppc_cpu_run_single(int); +void PPCCALL ppc_cpu_run_continuous(); +void PPCCALL ppc_cpu_run_single(int); uint32 ppc_cpu_get_gpr(int cpu, int i); void ppc_cpu_set_gpr(int cpu, int i, uint32 newvalue); void ppc_cpu_set_msr(int cpu, uint32 newvalue); -void ppc_cpu_set_pc(int cpu, uint32 newvalue); +void PPCCALL ppc_cpu_set_pc(int cpu, uint32 newvalue); uint32 ppc_cpu_get_pc(int cpu); uint32 ppc_cpu_get_pvr(int cpu); diff --git a/ppc/pearpc/cpu/cpu_generic/ppc_cpu.cpp b/ppc/pearpc/cpu/cpu_generic/ppc_cpu.cpp index f483de17..ee5c4543 100644 --- a/ppc/pearpc/cpu/cpu_generic/ppc_cpu.cpp +++ b/ppc/pearpc/cpu/cpu_generic/ppc_cpu.cpp @@ -37,7 +37,7 @@ #include "ppc_exc.h" #include "ppc_mmu.h" #include "ppc_tools.h" -#include "ppc.h" +#include "uae/ppc.h" //#include "io/graphic/gcard.h" @@ -53,7 +53,7 @@ static inline void ppc_debug_hook() sys_mutex exception_mutex; -void ppc_cpu_atomic_raise_ext_exception() +void PPCCALL ppc_cpu_atomic_raise_ext_exception() { sys_lock_mutex(exception_mutex); gCPU.ext_exception = true; @@ -61,7 +61,7 @@ void ppc_cpu_atomic_raise_ext_exception() sys_unlock_mutex(exception_mutex); } -void ppc_cpu_atomic_cancel_ext_exception() +void PPCCALL ppc_cpu_atomic_cancel_ext_exception() { sys_lock_mutex(exception_mutex); gCPU.ext_exception = false; @@ -94,12 +94,12 @@ static void ppc_do_dec(int val) } } -uint64_t ppc_cpu_get_dec(void) +uint64_t PPCCALL ppc_cpu_get_dec(void) { return gCPU.pdec; } -void ppc_cpu_do_dec(int val) +void PPCCALL ppc_cpu_do_dec(int val) { ppc_do_dec(val); } @@ -107,7 +107,7 @@ void ppc_cpu_do_dec(int val) static uint ops = 0; static int ppc_trace; -void ppc_cpu_run_single(int count) +void PPCCALL ppc_cpu_run_single(int count) { while (count != 0) { if (count > 0) @@ -219,7 +219,7 @@ void ppc_cpu_run_single(int count) } } -void ppc_cpu_run_continuous(void) +void PPCCALL ppc_cpu_run_continuous(void) { PPC_CPU_TRACE("execution started at %08x\n", gCPU.pc); gCPU.effective_code_page = 0xffffffff; @@ -227,7 +227,7 @@ void ppc_cpu_run_continuous(void) ppc_cpu_run_single(-1); } -void ppc_cpu_stop() +void PPCCALL ppc_cpu_stop() { sys_lock_mutex(exception_mutex); gCPU.stop_exception = true; @@ -272,7 +272,7 @@ void ppc_cpu_set_msr(int cpu, uint32 newvalue) } // Handle as CPU reset -void ppc_cpu_set_pc(int cpu, uint32 newvalue) +void PPCCALL ppc_cpu_set_pc(int cpu, uint32 newvalue) { gCPU.srr[0] = gCPU.pc; gCPU.srr[1] = gCPU.msr & 0xff73; @@ -324,7 +324,7 @@ void ppc_set_singlestep_nonverbose(bool v) //#include "configparser.h" -bool ppc_cpu_init(uint32 pvr) +bool PPCCALL ppc_cpu_init(uint32 pvr) { memset(&gCPU, 0, sizeof gCPU); gCPU.pvr = pvr; //gConfig->getConfigInt(CPU_KEY_PVR); @@ -346,7 +346,7 @@ bool ppc_cpu_init(uint32 pvr) return true; } -void ppc_cpu_free(void) +void PPCCALL ppc_cpu_free(void) { sys_destroy_mutex(exception_mutex); } diff --git a/ppc/pearpc/cpu/cpu_generic/ppc_cpu.h b/ppc/pearpc/cpu/cpu_generic/ppc_cpu.h index 2f4c5753..0018ad12 100644 --- a/ppc/pearpc/cpu/cpu_generic/ppc_cpu.h +++ b/ppc/pearpc/cpu/cpu_generic/ppc_cpu.h @@ -106,8 +106,10 @@ struct PPC_CPU_State { extern PPC_CPU_State gCPU; -void ppc_cpu_atomic_raise_ext_exception(); -void ppc_cpu_atomic_cancel_ext_exception(); +#include "uae/ppc.h" + +void PPCCALL ppc_cpu_atomic_raise_ext_exception(); +void PPCCALL ppc_cpu_atomic_cancel_ext_exception(); extern uint32 gBreakpoint; extern uint32 gBreakpoint2; diff --git a/ppc/pearpc/io/io.h b/ppc/pearpc/io/io.h index 90966320..d7ffa38e 100644 --- a/ppc/pearpc/io/io.h +++ b/ppc/pearpc/io/io.h @@ -39,7 +39,7 @@ #define IO_MEM_ACCESS_EXC 1 #define IO_MEM_ACCESS_FATAL 2 -#include "ppc.h" +#include "uae/ppc.h" static inline int io_mem_write(uint32 addr, uint32 data, int size) { diff --git a/ppc/pearpc/uaeglue.cpp b/ppc/pearpc/uaeglue.cpp index f512c384..145b1403 100644 --- a/ppc/pearpc/uaeglue.cpp +++ b/ppc/pearpc/uaeglue.cpp @@ -5,15 +5,15 @@ #include "system/systhread.h" -void write_log(const char *format, ...); +extern void write_log (const char *, ...); int ht_printf(const char *fmt,...) { char buffer[1000]; va_list parms; va_start(parms, fmt); - vsprintf(buffer, fmt, parms); - write_log(buffer); + vsnprintf(buffer, 1000, fmt, parms); + write_log("%s", buffer); va_end(parms); return 0; } @@ -43,3 +43,32 @@ void prom_quiesce() { } #endif + +#include "sysconfig.h" +#include "sysdeps.h" +#include + +typedef void * sys_mutex; + +int sys_lock_mutex(sys_mutex m) +{ + uae_sem_wait(&m); + return 1; +} + +void sys_unlock_mutex(sys_mutex m) +{ + uae_sem_post(&m); +} + +int sys_create_mutex(sys_mutex *m) +{ + if (!(*m)) + uae_sem_init(m, 0, 1); + return 1; +} + +void sys_destroy_mutex(sys_mutex m) +{ + uae_sem_destroy(&m); +} diff --git a/ppc/ppc.cpp b/ppc/ppc.cpp index 0501b3a8..5b3cce87 100644 --- a/ppc/ppc.cpp +++ b/ppc/ppc.cpp @@ -8,13 +8,9 @@ #include "debug.h" #include "custom.h" #include "uae.h" +#include "uae/dlopen.h" -#if defined(__cplusplus) && defined(WITH_QEMU_CPU) -#define PPC_EXTERN_C extern "C" -#endif - -#include "ppc.h" -//#include "ppc-if.h" +#include "uae/ppc.h" #ifdef WITH_PEARPC_CPU #include "pearpc/cpu/cpu.h" @@ -25,6 +21,8 @@ #define PPC_SYNC_WRITE 0 #define PPC_ACCESS_LOG 2 +#define TRACE(format, ...) write_log(_T("PPC: ---------------- ") format, ## __VA_ARGS__) + volatile int ppc_state; static volatile bool ppc_thread_running; @@ -42,9 +40,178 @@ static bool ppc_init_done; #define KB * 1024 #define MB * (1024 * 1024) -static void map_banks(void) +/* Dummy PPC implementation */ + +static bool PPCCALL dummy_ppc_cpu_init(uint32_t pvr) { return false; } +static void PPCCALL dummy_ppc_cpu_free(void) { } +static void PPCCALL dummy_ppc_cpu_stop(void) { } +static void PPCCALL dummy_ppc_cpu_atomic_raise_ext_exception(void) { } +static void PPCCALL dummy_ppc_cpu_atomic_cancel_ext_exception(void) { } +static void PPCCALL dummy_ppc_cpu_map_memory(uint32_t addr, uint32_t size, void *memory, const char *name) { } +static void PPCCALL dummy_ppc_cpu_set_pc(int cpu, uint32_t value) { } +static void PPCCALL dummy_ppc_cpu_run_continuous(void) { } +static void PPCCALL dummy_ppc_cpu_run_single(int count) { } +static uint64_t PPCCALL dummy_ppc_cpu_get_dec(void) { return 0; } +static void PPCCALL dummy_ppc_cpu_do_dec(int value) { } + +/* Functions typedefs for PPC implementation */ + +typedef bool (PPCCALL *ppc_cpu_init_function)(uint32_t pvr); +typedef void (PPCCALL *ppc_cpu_free_function)(void); +typedef void (PPCCALL *ppc_cpu_stop_function)(void); +typedef void (PPCCALL *ppc_cpu_atomic_raise_ext_exception_function)(void); +typedef void (PPCCALL *ppc_cpu_atomic_cancel_ext_exception_function)(void); +typedef void (PPCCALL *ppc_cpu_map_memory_function)(uint32_t addr, uint32_t size, void *memory, const char *name); +typedef void (PPCCALL *ppc_cpu_set_pc_function)(int cpu, uint32_t value); +typedef void (PPCCALL *ppc_cpu_run_continuous_function)(void); +typedef void (PPCCALL *ppc_cpu_run_single_function)(int count); +typedef uint64_t (PPCCALL *ppc_cpu_get_dec_function)(void); +typedef void (PPCCALL *ppc_cpu_do_dec_function)(int value); + +/* Function pointers to active PPC implementation */ + +static ppc_cpu_init_function g_ppc_cpu_init; +static ppc_cpu_free_function g_ppc_cpu_free; +static ppc_cpu_stop_function g_ppc_cpu_stop; +static ppc_cpu_atomic_raise_ext_exception_function g_ppc_cpu_atomic_raise_ext_exception; +static ppc_cpu_atomic_cancel_ext_exception_function g_ppc_cpu_atomic_cancel_ext_exception; +static ppc_cpu_map_memory_function g_ppc_cpu_map_memory; +static ppc_cpu_set_pc_function g_ppc_cpu_set_pc; +static ppc_cpu_run_continuous_function g_ppc_cpu_run_continuous; +static ppc_cpu_run_single_function g_ppc_cpu_run_single; +static ppc_cpu_get_dec_function g_ppc_cpu_get_dec; +static ppc_cpu_do_dec_function g_ppc_cpu_do_dec; + +static void load_dummy_implementation() { + write_log(_T("PPC: Loading dummy implementation\n")); + g_ppc_cpu_init = dummy_ppc_cpu_init; + g_ppc_cpu_free = dummy_ppc_cpu_free; + g_ppc_cpu_stop = dummy_ppc_cpu_stop; + g_ppc_cpu_atomic_raise_ext_exception = dummy_ppc_cpu_atomic_raise_ext_exception; + g_ppc_cpu_atomic_cancel_ext_exception = dummy_ppc_cpu_atomic_cancel_ext_exception; + g_ppc_cpu_map_memory = dummy_ppc_cpu_map_memory; + g_ppc_cpu_set_pc = dummy_ppc_cpu_set_pc; + g_ppc_cpu_run_continuous = dummy_ppc_cpu_run_continuous; + g_ppc_cpu_run_single = dummy_ppc_cpu_run_single; + g_ppc_cpu_get_dec = dummy_ppc_cpu_get_dec; + g_ppc_cpu_do_dec = dummy_ppc_cpu_do_dec; +} + #ifdef WITH_QEMU_CPU + +static void uae_patch_library_ppc(UAE_DLHANDLE handle) +{ + void *ptr; + + ptr = uae_dlsym(handle, "uae_ppc_io_mem_read"); + if (ptr) *((uae_ppc_io_mem_read_function *) ptr) = &uae_ppc_io_mem_read; + else write_log(_T("WARNING: uae_ppc_io_mem_read not set\n")); + + ptr = uae_dlsym(handle, "uae_ppc_io_mem_write"); + if (ptr) *((uae_ppc_io_mem_write_function *) ptr) = &uae_ppc_io_mem_write; + else write_log(_T("WARNING: uae_ppc_io_mem_write not set\n")); + + ptr = uae_dlsym(handle, "uae_ppc_io_mem_read64"); + if (ptr) *((uae_ppc_io_mem_read64_function *) ptr) = &uae_ppc_io_mem_read64; + else write_log(_T("WARNING: uae_ppc_io_mem_read64 not set\n")); + + ptr = uae_dlsym(handle, "uae_ppc_io_mem_write64"); + if (ptr) *((uae_ppc_io_mem_write64_function *) ptr) = &uae_ppc_io_mem_write64; + else write_log(_T("WARNING: uae_ppc_io_mem_write64 not set\n")); +} + +static bool load_qemu_implementation() +{ + write_log(_T("PPC: Loading QEmu implementation\n")); + // FIXME: replace with a callback to get the qemu path (so it can be + // implemented separately by WinUAE and FS-UAE. + UAE_DLHANDLE handle = uae_dlopen(_T("qemu-uae.dll")); + if (!handle) { + write_log(_T("Error loading qemu-uae library\n")); + return false; + } + write_log(_T("PPC: Loaded qemu-uae library at %p\n"), handle); + + /* get function pointers */ + g_ppc_cpu_init = (ppc_cpu_init_function) uae_dlsym(handle, "ppc_cpu_init"); + g_ppc_cpu_free = (ppc_cpu_free_function) uae_dlsym(handle, "ppc_cpu_free"); + g_ppc_cpu_stop = (ppc_cpu_stop_function) uae_dlsym(handle, "ppc_cpu_stop"); + g_ppc_cpu_atomic_raise_ext_exception = (ppc_cpu_atomic_raise_ext_exception_function) uae_dlsym(handle, "ppc_cpu_atomic_raise_ext_exception"); + g_ppc_cpu_atomic_cancel_ext_exception = (ppc_cpu_atomic_cancel_ext_exception_function) uae_dlsym(handle, "ppc_cpu_atomic_cancel_ext_exception"); + g_ppc_cpu_map_memory = (ppc_cpu_map_memory_function) uae_dlsym(handle, "ppc_cpu_map_memory"); + g_ppc_cpu_set_pc = (ppc_cpu_set_pc_function) uae_dlsym(handle, "ppc_cpu_set_pc"); + g_ppc_cpu_run_continuous = (ppc_cpu_run_continuous_function) uae_dlsym(handle, "ppc_cpu_run_continuous"); + g_ppc_cpu_run_single = (ppc_cpu_run_single_function) uae_dlsym(handle, "ppc_cpu_run_single"); + g_ppc_cpu_get_dec = (ppc_cpu_get_dec_function) uae_dlsym(handle, "ppc_cpu_get_dec"); + g_ppc_cpu_do_dec = (ppc_cpu_do_dec_function) uae_dlsym(handle, "ppc_cpu_do_dec"); + +#if 0 + /* register callback functions */ +#endif + + uae_patch_library_common(handle); + uae_patch_library_ppc(handle); + return true; +} + +#endif + +#ifdef WITH_PEARPC_CPU + +static bool load_pearpc_implementation() +{ + write_log(_T("PPC: Loading PearPC implementation\n")); + g_ppc_cpu_init = ppc_cpu_init; + g_ppc_cpu_free = ppc_cpu_free; + g_ppc_cpu_stop = ppc_cpu_stop; + g_ppc_cpu_atomic_raise_ext_exception = ppc_cpu_atomic_raise_ext_exception; + g_ppc_cpu_atomic_cancel_ext_exception = ppc_cpu_atomic_cancel_ext_exception; + + g_ppc_cpu_map_memory = dummy_ppc_cpu_map_memory; + + g_ppc_cpu_set_pc = ppc_cpu_set_pc; + g_ppc_cpu_run_continuous = ppc_cpu_run_continuous; + g_ppc_cpu_run_single = ppc_cpu_run_single; + g_ppc_cpu_get_dec = ppc_cpu_get_dec; + g_ppc_cpu_do_dec = ppc_cpu_do_dec; + return true; +} + +#endif + +static void load_ppc_implementation() +{ + int impl = currprefs.ppc_implementation; +#ifdef WITH_PEARPC_CPU + if (impl == PPC_IMPLEMENTATION_AUTO || impl == PPC_IMPLEMENTATION_PEARPC) { + if (load_pearpc_implementation()) { + return; + } + } +#endif +#ifdef WITH_QEMU_CPU + if (impl == PPC_IMPLEMENTATION_AUTO || impl == PPC_IMPLEMENTATION_QEMU) { + if (load_qemu_implementation()) { + return; + } + } +#endif + load_dummy_implementation(); +} + +static void initialize() +{ + static bool initialized = false; + if (initialized) { + return; + } + initialized = true; + load_ppc_implementation(); +} + +static void map_banks(void) +{ /* * Use NULL to get callbacks to uae_ppc_io_mem_read/write. Use real * memory address for direct access to RAM banks (looks like this @@ -54,50 +221,47 @@ static void map_banks(void) // FIXME: hack, replace with automatic / dynamic mapping #if 1 - ppc_cpu_map_memory(0x00000000, 2048 KB, NULL, "Chip memory"); - ppc_cpu_map_memory(0x00BF0000, 64 KB, NULL, "CIA"); - ppc_cpu_map_memory(0x00F00000, 256 KB, get_real_address(0x00F00000), "CPUBoard F00000"); - ppc_cpu_map_memory(0x00F50000, 192 KB, NULL, "CPUBoard IO"); - ppc_cpu_map_memory(0x00DF0000, 64 KB, NULL, "Custom chipset"); - ppc_cpu_map_memory(0x08000000, 128 MB, get_real_address(0x08000000), "RAMSEY memory (high)"); - ppc_cpu_map_memory(0xFFF00000, 512 KB, get_real_address(0xFFF00000), "CPUBoard MAPROM"); + g_ppc_cpu_map_memory(0x00000000, 2048 KB, NULL, "Chip memory"); + g_ppc_cpu_map_memory(0x00BF0000, 64 KB, NULL, "CIA"); + g_ppc_cpu_map_memory(0x00F00000, 256 KB, get_real_address(0x00F00000), "CPUBoard F00000"); + g_ppc_cpu_map_memory(0x00F50000, 192 KB, NULL, "CPUBoard IO"); + g_ppc_cpu_map_memory(0x00DF0000, 64 KB, NULL, "Custom chipset"); + g_ppc_cpu_map_memory(0x08000000, 16 MB, get_real_address(0x08000000), "RAMSEY memory (high)"); + g_ppc_cpu_map_memory(0xFFF00000, 512 KB, get_real_address(0xFFF00000), "CPUBoard MAPROM"); #else - ppc_cpu_map_memory(0x00BF0000, 64 KB, NULL, "CIA"); - ppc_cpu_map_memory(0x00F00000, 256 KB, NULL, "CPUBoard F00000"); - ppc_cpu_map_memory(0x00F50000, 192 KB, NULL, "CPUBoard IO"); - ppc_cpu_map_memory(0x08000000, 128 MB, NULL, "RAMSEY memory (high)"); - ppc_cpu_map_memory(0xFFF00000, 512 KB, get_real_address(0xFFF00000), "CPUBoard MAPROM"); -#endif + g_ppc_cpu_map_memory(0x00BF0000, 64 KB, NULL, "CIA"); + g_ppc_cpu_map_memory(0x00F00000, 256 KB, NULL, "CPUBoard F00000"); + g_ppc_cpu_map_memory(0x00F50000, 192 KB, NULL, "CPUBoard IO"); + g_ppc_cpu_map_memory(0x08000000, 16 MB, NULL, "RAMSEY memory (high)"); + g_ppc_cpu_map_memory(0xFFF00000, 512 KB, get_real_address(0xFFF00000), "CPUBoard MAPROM"); #endif } static void uae_ppc_cpu_reset(void) { -#ifdef WITH_PPC - write_log("---- uae_ppc_cpu_reset ----\n"); + TRACE(_T("uae_ppc_cpu_reset\n")); + initialize(); if (!ppc_init_done) { write_log(_T("PPC: Hard reset\n")); - ppc_cpu_init(currprefs.cpuboard_type == BOARD_BLIZZARDPPC ? BLIZZPPC_PVR : CSPPC_PVR); + g_ppc_cpu_init(currprefs.cpuboard_type == BOARD_BLIZZARDPPC ? BLIZZPPC_PVR : CSPPC_PVR); map_banks(); ppc_init_done = true; } write_log(_T("PPC: Init\n")); - ppc_cpu_set_pc(0, 0xfff00100); + g_ppc_cpu_set_pc(0, 0xfff00100); ppc_cycle_count = 2000; ppc_state = PPC_STATE_ACTIVE; ppc_cpu_lock_state = 0; -#endif } static void *ppc_thread(void *v) { -#ifdef WITH_PPC for (;;) { uae_u32 v = read_comm_pipe_u32_blocking(&ppcrequests); if (v == 0xffffffff) break; uae_ppc_cpu_reset(); - ppc_cpu_run_continuous(); + g_ppc_cpu_run_continuous(); if (ppc_state == PPC_STATE_ACTIVE || ppc_state == PPC_STATE_SLEEP) ppc_state = PPC_STATE_STOP; write_log(_T("ppc_cpu_run() exited.\n")); @@ -105,13 +269,12 @@ static void *ppc_thread(void *v) } ppc_thread_running = false; -#endif return NULL; } void uae_ppc_to_main_thread(void) { - write_log("---- uae_ppc_to_main_thread ----\n"); + TRACE(_T("uae_ppc_to_main_thread\n")); if (ppc_thread_running) { write_log(_T("PPC: transferring PPC emulation to main thread.\n")); uae_ppc_cpu_stop(); @@ -128,11 +291,9 @@ void uae_ppc_to_main_thread(void) void uae_ppc_emulate(void) { -#ifdef WITH_PPC - write_log("---- uae_ppc_emulate ----\n"); + TRACE(_T("uae_ppc_emulate\n")); if (ppc_state == PPC_STATE_ACTIVE || ppc_state == PPC_STATE_SLEEP) - ppc_cpu_run_single(10); -#endif + g_ppc_cpu_run_single(10); } bool uae_ppc_poll_queue(void) @@ -213,7 +374,7 @@ bool uae_ppc_direct_physical_memory_handle(uint32_t addr, uint8_t *&ptr) return false; } -PPC_EXTERN_C bool uae_ppc_io_mem_write(uint32_t addr, uint32_t data, int size) +bool UAECALL uae_ppc_io_mem_write(uint32_t addr, uint32_t data, int size) { while (ppc_thread_running && ppc_cpu_lock_state < 0 && ppc_state); @@ -257,7 +418,7 @@ PPC_EXTERN_C bool uae_ppc_io_mem_write(uint32_t addr, uint32_t data, int size) return true; } -PPC_EXTERN_C bool uae_ppc_io_mem_read(uint32_t addr, uint32_t *data, int size) +bool UAECALL uae_ppc_io_mem_read(uint32_t addr, uint32_t *data, int size) { uint32_t v; @@ -274,11 +435,6 @@ PPC_EXTERN_C bool uae_ppc_io_mem_read(uint32_t addr, uint32_t *data, int size) *data = v; return true; } -#if PPC_ACCESS_LOG > 0 - if (!ppc_thread_running && !valid_address(addr, size)) { - write_log(_T("PPC io read %08x=%08x %d\n"), addr, v, size); - } -#endif switch (size) { case 4: @@ -296,13 +452,18 @@ PPC_EXTERN_C bool uae_ppc_io_mem_read(uint32_t addr, uint32_t *data, int size) } *data = v; +#if PPC_ACCESS_LOG > 0 + if (!ppc_thread_running && !valid_address(addr, size)) { + write_log(_T("PPC io read %08x=%08x %d\n"), addr, v, size); + } +#endif #if PPC_ACCESS_LOG > 2 write_log(_T("PPC mem read %08x=%08x %d\n"), addr, v, size); #endif return true; } -bool uae_ppc_io_mem_write64(uint32_t addr, uint64_t data) +bool UAECALL uae_ppc_io_mem_write64(uint32_t addr, uint64_t data) { while (ppc_thread_running && ppc_cpu_lock_state < 0 && ppc_state); @@ -329,7 +490,7 @@ bool uae_ppc_io_mem_write64(uint32_t addr, uint64_t data) return true; } -bool uae_ppc_io_mem_read64(uint32_t addr, uint64_t *data) +bool UAECALL uae_ppc_io_mem_read64(uint32_t addr, uint64_t *data) { uint32_t v1, v2; @@ -357,12 +518,11 @@ bool uae_ppc_io_mem_read64(uint32_t addr, uint64_t *data) void uae_ppc_cpu_stop(void) { - write_log("---- uae_ppc_cpu_stop ----\n"); -#ifdef WITH_PPC + TRACE(_T("uae_ppc_cpu_stop\n")); if (ppc_thread_running && ppc_state) { write_log(_T("Stopping PPC.\n")); uae_ppc_wakeup(); - ppc_cpu_stop(); + g_ppc_cpu_stop(); while (ppc_state != PPC_STATE_STOP && ppc_state != PPC_STATE_CRASH) { uae_ppc_wakeup(); uae_ppc_poll_queue(); @@ -371,13 +531,11 @@ void uae_ppc_cpu_stop(void) ppc_state = PPC_STATE_STOP; write_log(_T("PPC stopped.\n")); } -#endif } void uae_ppc_cpu_reboot(void) { - write_log("---- uae_ppc_cpu_reboot ----\n"); -#ifdef WITH_PPC + TRACE(_T("uae_ppc_cpu_reboot\n")); if (ppc_main_thread) { uae_ppc_cpu_reset(); } else { @@ -393,26 +551,22 @@ void uae_ppc_cpu_reboot(void) } write_comm_pipe_u32(&ppcrequests, 1, 1); } -#endif } void uae_ppc_reset(bool hardreset) { - write_log("---- uae_ppc_reset ----\n"); -#ifdef WITH_PPC + TRACE(_T("uae_ppc_reset hardreset=%d\n"), hardreset); uae_ppc_cpu_stop(); ppc_main_thread = false; if (hardreset) { if (ppc_init_done) - ppc_cpu_free(); + g_ppc_cpu_free(); ppc_init_done = false; } -#endif } void uae_ppc_cpu_lock(void) { -#ifdef WITH_PPC // when called, lock was already set by other CPU if (ppc_access) { // ppc accessing but m68k already locked @@ -421,143 +575,60 @@ void uae_ppc_cpu_lock(void) // m68k accessing but ppc already locked ppc_cpu_lock_state = 1; } -#endif } + bool uae_ppc_cpu_unlock(void) { -#ifdef WITH_PPC if (!ppc_cpu_lock_state) return true; ppc_cpu_lock_state = 0; return false; -#endif } void uae_ppc_wakeup(void) { - write_log("---- uae_ppc_wakeup ----\n"); -#ifdef WITH_PPC + TRACE(_T("uae_ppc_wakeup\n")); if (ppc_state == PPC_STATE_SLEEP) ppc_state = PPC_STATE_ACTIVE; -#endif } void uae_ppc_interrupt(bool active) { - write_log("---- uae_ppc_interrupt ----\n"); -#ifdef WITH_PPC + TRACE(_T("uae_ppc_interrupt\n")); if (active) { - ppc_cpu_atomic_raise_ext_exception(); + g_ppc_cpu_atomic_raise_ext_exception(); uae_ppc_wakeup(); } else { - ppc_cpu_atomic_cancel_ext_exception(); + g_ppc_cpu_atomic_cancel_ext_exception(); } -#endif } // sleep until interrupt (or PPC stopped) void uae_ppc_doze(void) { - write_log("---- uae_ppc_doze ----\n"); -#ifdef WITH_PPC + TRACE(_T("uae_ppc_doze\n")); if (!ppc_thread_running) return; ppc_state = PPC_STATE_SLEEP; while (ppc_state == PPC_STATE_SLEEP) { sleep_millis(2); } -#endif } void uae_ppc_crash(void) { - write_log("---- uae_ppc_crash ----\n"); -#ifdef WITH_PPC + TRACE(_T("uae_ppc_crash\n")); ppc_state = PPC_STATE_CRASH; - ppc_cpu_stop(); -#endif + g_ppc_cpu_stop(); } void uae_ppc_hsync_handler(void) { -#ifdef WITH_PPC if (ppc_state != PPC_STATE_SLEEP) return; - if (ppc_cpu_get_dec() == 0) { + if (g_ppc_cpu_get_dec() == 0) { uae_ppc_wakeup(); } else { - ppc_cpu_do_dec(ppc_cycle_count); + g_ppc_cpu_do_dec(ppc_cycle_count); } -#endif } - -#ifdef WITH_PEARPC_CPU - -typedef void * sys_mutex; - -int sys_lock_mutex(sys_mutex m) -{ - uae_sem_wait(&m); - return 1; -} - -void sys_unlock_mutex(sys_mutex m) -{ - uae_sem_post(&m); -} - -int sys_create_mutex(sys_mutex *m) -{ - if (!(*m)) - uae_sem_init(m, 0, 1); - return 1; -} - -void sys_destroy_mutex(sys_mutex m) -{ - uae_sem_destroy(&m); -} - -#endif - -#ifndef _MSV_VER -#define __cdecl -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -void __cdecl pixman_format_supported_source(void); -void __cdecl pixman_format_supported_source(void) { } - -void __cdecl pixman_image_composite(void); -void __cdecl pixman_image_composite(void) { } - -void __cdecl pixman_image_create_bits(void); -void __cdecl pixman_image_create_bits(void) { } - -void __cdecl pixman_image_create_solid_fill(void); -void __cdecl pixman_image_create_solid_fill(void) { } - -void __cdecl pixman_image_fill_rectangles(void); -void __cdecl pixman_image_fill_rectangles(void) { } - -void __cdecl pixman_image_get_data(void); -void __cdecl pixman_image_get_data(void) { } - -void __cdecl pixman_image_get_height(void); -void __cdecl pixman_image_get_height(void) { } - -void __cdecl pixman_image_get_width(void); -void __cdecl pixman_image_get_width(void) { } - -void __cdecl pixman_image_get_stride(void); -void __cdecl pixman_image_get_stride(void) { } - -void __cdecl pixman_image_unref(void); -void __cdecl pixman_image_unref(void) { } - -#ifdef __cplusplus -} -#endif diff --git a/ppc/ppcglue.cpp b/ppc/ppcglue.cpp new file mode 100644 index 00000000..0fa612bc --- /dev/null +++ b/ppc/ppcglue.cpp @@ -0,0 +1,113 @@ + +#include +#include +#include + +void write_log (const char *format, ...); + +extern "C" +{ +extern void __cdecl ppc_translate_init(void); + +int __cdecl snprintf (char * s, size_t n, const char * format, ... ) +{ + return 0; +} + +int __cdecl __mingw_vprintf(const char * format, va_list arg) +{ + return 0; +} + +int __cdecl __mingw_vfprintf(void *stream, const char * format, va_list arg) +{ + return 0; +} + +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; + +void __cdecl gettimeofday(struct timeval *tv, void *blah) +{ + struct timeb time; + + ftime (&time); + + tv->tv_sec = time.time; + tv->tv_usec = time.millitm * 1000; +} + +void __cdecl inflateInit2_(void) +{ +} +void __cdecl inflate(void) +{ +} +void __cdecl inflateEnd(void) +{ +} +void __cdecl compress2(void) +{ +} +void __cdecl compressBound(void) +{ +} + +void __cdecl opendir(void) +{ +} +void __cdecl readdir(void) +{ +} +void __cdecl closedir(void) +{ +} + +void __cdecl popen(void) +{ +} +void __cdecl pclose(void) +{ +} + +void __cdecl pixman_format_supported_source(void) { } +void __cdecl pixman_image_composite(void) { } +void __cdecl pixman_image_create_bits(void) { } +void __cdecl pixman_image_create_solid_fill(void) { } +void __cdecl pixman_image_fill_rectangles(void) { } +void __cdecl pixman_image_get_data(void) { } +void __cdecl pixman_image_get_height(void) { } +void __cdecl pixman_image_get_width(void) { } +void __cdecl pixman_image_get_stride(void) { } +void __cdecl pixman_image_unref(void) { } + +int optarg; +int optind; +int getopt; + +void __cdecl __emutls_get_address(void) +{ +} + +int __cdecl sizeof_CPUPPCState(void); +int __cdecl sizeof_PowerPCCPU(void); + +void * __cdecl cpu_ppc_init(const char *cpu_model); + + +} + +void crap(void) +{ + const char *cpu_model = "604e"; + void *cpu, *env; + int cpu_size, env_size; + + cpu_size = sizeof_CPUPPCState(); + env_size = sizeof_PowerPCCPU(); + + cpu = cpu_ppc_init(cpu_model); + +}