From: Toni Wilen Date: Sun, 12 Oct 2014 16:29:59 +0000 (+0300) Subject: 2900b20 X-Git-Tag: 3000~22 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=8cce4b50d462898a7cdddcceb45fe8fc6d27dfa9;p=francis%2Fwinuae.git 2900b20 --- diff --git a/debug.cpp b/debug.cpp index 610cfd45..241483ec 100644 --- a/debug.cpp +++ b/debug.cpp @@ -2998,7 +2998,9 @@ static void memory_map_dump_3(UaeMemoryMap *map, int log) tmp[0] = 0; if ((a1->flags & ABFLAG_ROM) && mirrored) { TCHAR *p = txt + _tcslen (txt); - uae_u32 crc = get_crc32 (a1->xlateaddr((j << 16) | bankoffset), (size * 1024) / mirrored); + uae_u32 crc = 0xffffffff; + if (a1->check(((j << 16) | bankoffset), (size * 1024) / mirrored)) + crc = get_crc32 (a1->xlateaddr((j << 16) | bankoffset), (size * 1024) / mirrored); struct romdata *rd = getromdatabycrc (crc); _stprintf (p, _T(" (%08X)"), crc); if (rd) { diff --git a/include/uae/qemu.h b/include/uae/qemu.h new file mode 100644 index 00000000..22833702 --- /dev/null +++ b/include/uae/qemu.h @@ -0,0 +1,69 @@ +#ifndef UAE_QEMU_H +#define UAE_QEMU_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" + +/* The qemu-uae major version must match this */ +#define QEMU_UAE_VERSION_MAJOR 3 + +/* The qemu-uae minor version must be at least this */ +#define QEMU_UAE_VERSION_MINOR 3 + +UAE_DECLARE_IMPORT_FUNCTION( + void, qemu_uae_version, int *major, int *minor, int *revision) +UAE_DECLARE_IMPORT_FUNCTION( + void, qemu_uae_init, void) +UAE_DECLARE_IMPORT_FUNCTION( + void, qemu_uae_start, void) +UAE_DECLARE_IMPORT_FUNCTION( + int, qemu_uae_lock, int) + +UAE_DECLARE_IMPORT_FUNCTION( + void, qemu_uae_slirp_init, void) +UAE_DECLARE_IMPORT_FUNCTION( + void, qemu_uae_slirp_input, const uint8_t *pkt, int pkt_len) + +UAE_DECLARE_EXPORT_FUNCTION( + void, uae_slirp_output, const uint8_t *pkt, int pkt_len) + +UAE_DECLARE_IMPORT_FUNCTION( + bool, qemu_uae_ppc_init, const char* model, uint32_t hid1) +UAE_DECLARE_IMPORT_FUNCTION( + bool, qemu_uae_ppc_in_cpu_thread, void) +UAE_DECLARE_IMPORT_FUNCTION( + void, qemu_uae_ppc_external_interrupt, bool) + +#define QEMU_UAE_LOCK_TRYLOCK 1 +#define QEMU_UAE_LOCK_TRYLOCK_CANCEL 2 +#define QEMU_UAE_LOCK_ACQUIRE 3 +#define QEMU_UAE_LOCK_RELEASE 4 + +#ifdef UAE + +#include "uae/dlopen.h" + +UAE_DLHANDLE uae_qemu_uae_init(void); + +#endif /* UAE */ + +#if 0 +#ifdef UAE +typedef void (QEMUCALL *qemu_uae_version_function)(int *major, int *minor, + int *revision); +extern qemu_uae_version_function qemu_uae_version; +#else +void qemu_uae_version(int *major, int *minor, int *revision); +#endif + +#ifdef UAE +typedef void (QEMUCALL *qemu_uae_init_function)(void); +extern qemu_uae_init_function qemu_uae_init; +#else +void qemu_uae_init(void); +#endif +#endif + +#endif /* UAE_QEMU_H */ diff --git a/od-win32/win32.h b/od-win32/win32.h index 83f74b0f..c99962bf 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -20,12 +20,12 @@ #define LANG_DLL_FULL_VERSION_MATCH 1 #if WINUAEPUBLICBETA -#define WINUAEBETA _T("19") +#define WINUAEBETA _T("20") #else #define WINUAEBETA _T("") #endif -#define WINUAEDATE MAKEBD(2014, 10, 6) +#define WINUAEDATE MAKEBD(2014, 10, 12) //#define WINUAEEXTRA _T("AmiKit Preview") //#define WINUAEEXTRA _T("Amiga Forever Edition") diff --git a/od-win32/winuae_msvc11/winuae_msvc.vcxproj b/od-win32/winuae_msvc11/winuae_msvc.vcxproj index 088bbb35..b17339e3 100644 --- a/od-win32/winuae_msvc11/winuae_msvc.vcxproj +++ b/od-win32/winuae_msvc11/winuae_msvc.vcxproj @@ -793,6 +793,7 @@ + diff --git a/od-win32/winuae_msvc11/winuae_msvc.vcxproj.filters b/od-win32/winuae_msvc11/winuae_msvc.vcxproj.filters index cc787cc1..70db4f03 100644 --- a/od-win32/winuae_msvc11/winuae_msvc.vcxproj.filters +++ b/od-win32/winuae_msvc11/winuae_msvc.vcxproj.filters @@ -706,6 +706,9 @@ common + + common + diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index 80e8295d..0a2828a8 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -18,9 +18,19 @@ Things that may happen in 2015: - restore only single input target to default. +Beta 20: + +- A2630 rom was not unmapped completely (only first half) +- CSMK3/CSPPC/BPPC Amiga reset bit should stop the PPC before reseting the system to prevent random hangs. +- CSMK3/CSPPC/BPPC switching off maprom programmatically (not hard reset) didn't restore original KS ROM. +- Added preliminary CDTV-CR emulation. Boots to title screen, preferences screen also works. Only clock + and 4k (nonvolatile?) RAM emulated. No CD, no nothing else. v3.32 extended ROM added to ROM scanner, + CDTV-CR option added to Quickstart. +- PPC interrupt/thread-safety hang problems should be fixed. + Beta 19: -- Restartarting and loading another config crashed if PPC or RTG without JIT direct was active. +- Restarting and loading another config crashed if PPC or RTG without JIT direct was active. - After restarting non-JIT config, JIT direct was not available (old restriction that should have been gone few official releases ago) - Added A2620/A2630 emulation and two rom images to rom scanner. (390282-06/390283-06 and 390282-07/390283-07) diff --git a/ppc/ppc.cpp b/ppc/ppc.cpp index b6571d65..1a8d885a 100644 --- a/ppc/ppc.cpp +++ b/ppc/ppc.cpp @@ -13,11 +13,7 @@ #include "uae/ppc.h" -/* The qemu-uae major version must match this */ -#define QEMU_UAE_VERSION_MAJOR 2 - -/* The qemu-uae minor version must be at least this */ -#define QEMU_UAE_VERSION_MINOR 0 +#include "uae/qemu.h" #define SPINLOCK_DEBUG 0 #define PPC_ACCESS_LOG 0 @@ -189,6 +185,10 @@ static struct impl { ppc_cpu_check_state_function check_state; ppc_cpu_set_state_function set_state; ppc_cpu_reset_function reset; + qemu_uae_ppc_in_cpu_thread_function in_cpu_thread; + qemu_uae_ppc_external_interrupt_function external_interrupt; + qemu_uae_lock_function lock; + } impl; static void load_dummy_implementation(void) @@ -247,8 +247,7 @@ static bool load_qemu_implementation(void) impl.init = (ppc_cpu_init_function) uae_dlsym(handle, "ppc_cpu_init"); //impl.free = (ppc_cpu_free_function) uae_dlsym(handle, "ppc_cpu_free"); //impl.stop = (ppc_cpu_stop_function) uae_dlsym(handle, "ppc_cpu_stop"); - impl.atomic_raise_ext_exception = (ppc_cpu_atomic_raise_ext_exception_function) uae_dlsym(handle, "ppc_cpu_atomic_raise_ext_exception"); - impl.atomic_cancel_ext_exception = (ppc_cpu_atomic_cancel_ext_exception_function) uae_dlsym(handle, "ppc_cpu_atomic_cancel_ext_exception"); + impl.external_interrupt = (qemu_uae_ppc_external_interrupt_function) uae_dlsym(handle, "qemu_uae_ppc_external_interrupt"); impl.map_memory = (ppc_cpu_map_memory_function) uae_dlsym(handle, "ppc_cpu_map_memory"); //impl.set_pc = (ppc_cpu_set_pc_function) uae_dlsym(handle, "ppc_cpu_set_pc"); impl.run_continuous = (ppc_cpu_run_continuous_function) uae_dlsym(handle, "ppc_cpu_run_continuous"); @@ -259,6 +258,8 @@ static bool load_qemu_implementation(void) impl.check_state = (ppc_cpu_check_state_function) uae_dlsym(handle, "ppc_cpu_check_state"); impl.set_state = (ppc_cpu_set_state_function) uae_dlsym(handle, "ppc_cpu_set_state"); impl.reset = (ppc_cpu_reset_function) uae_dlsym(handle, "ppc_cpu_reset"); + impl.in_cpu_thread = (qemu_uae_ppc_in_cpu_thread_function) uae_dlsym(handle, "qemu_uae_ppc_in_cpu_thread"); + impl.lock = (qemu_uae_lock_function) uae_dlsym(handle, "qemu_uae_lock"); /* Check major version (=) and minor version (>=) */ @@ -340,6 +341,64 @@ static bool using_pearpc(void) return ppc_implementation == PPC_IMPLEMENTATION_PEARPC; } +enum PPCLockMethod { + PPC_RELEASE_SPINLOCK, + PPC_KEEP_SPINLOCK, +}; + +enum PPCLockStatus { + PPC_NO_LOCK_NEEDED, + PPC_LOCKED, + PPC_LOCKED_WITHOUT_SPINLOCK, +}; + +static PPCLockStatus get_ppc_lock(PPCLockMethod method) +{ + if (impl.in_cpu_thread()) { + return PPC_NO_LOCK_NEEDED; + } else if (method == PPC_RELEASE_SPINLOCK) { + + uae_ppc_spinlock_release(); + impl.lock(QEMU_UAE_LOCK_ACQUIRE); + return PPC_LOCKED_WITHOUT_SPINLOCK; + + } else if (method == PPC_KEEP_SPINLOCK) { + + bool trylock_called = false; + while (true) { + if (ppc_spinlock_waiting) { + /* PPC CPU is waiting for the spinlock and the UAE side + * owns the spinlock - no additional locking needed */ + if (trylock_called) { + impl.lock(QEMU_UAE_LOCK_TRYLOCK_CANCEL); + } + return PPC_NO_LOCK_NEEDED; + } + int error = impl.lock(QEMU_UAE_LOCK_TRYLOCK); + if (error == 0) { + /* Lock succeeded */ + return PPC_LOCKED; + } + trylock_called = true; + } + } else { + write_log("?\n"); + return PPC_NO_LOCK_NEEDED; + } +} + +static void release_ppc_lock(PPCLockStatus status) +{ + if (status == PPC_NO_LOCK_NEEDED) { + return; + } else if (status == PPC_LOCKED_WITHOUT_SPINLOCK) { + impl.lock(QEMU_UAE_LOCK_RELEASE); + uae_ppc_spinlock_get(); + } else if (status == PPC_LOCKED) { + impl.lock(QEMU_UAE_LOCK_RELEASE); + } +} + static void initialize(void) { static bool initialized = false; @@ -380,7 +439,15 @@ static void map_banks(void) regions[i].alias = r->alias; regions[i].memory = r->memory; } + + if (impl.in_cpu_thread() == false) { + uae_ppc_spinlock_release(); + } impl.map_memory(regions, map.num_regions); + if (impl.in_cpu_thread() == false) { + uae_ppc_spinlock_get(); + } + for (int i = 0; i < map.num_regions; i++) { free((void*)regions[i].name); } @@ -400,14 +467,13 @@ static void set_and_wait_for_state(int state, int unlock) return; } if (using_qemu()) { - impl.set_state(state); - if (unlock) + if (impl.in_cpu_thread() == false) { uae_ppc_spinlock_release(); - while (!impl.check_state(state)) { - sleep_millis(1); } - if (unlock) - uae_ppc_spinlock_get(); + impl.set_state(state); + if (impl.in_cpu_thread() == false) { + uae_ppc_spinlock_get(); + } } } @@ -421,7 +487,16 @@ void ppc_map_banks(uae_u32 start, uae_u32 size, const TCHAR *name, void *addr, b r.name = ua(name); r.alias = remove ? 0xffffffff : 0; r.memory = addr; + + if (impl.in_cpu_thread() == false) { + /* map_memory will acquire the qemu global lock, so we must ensure + * the PPC CPU can finish any I/O requests and release the lock. */ + uae_ppc_spinlock_release(); + } impl.map_memory(&r, -1); + if (impl.in_cpu_thread() == false) { + uae_ppc_spinlock_get(); + } free((void*)r.name); } @@ -775,12 +850,19 @@ void uae_ppc_wakeup(void) void uae_ppc_interrupt(bool active) { //TRACE(_T("uae_ppc_interrupt\n")); - if (active) { - impl.atomic_raise_ext_exception(); - uae_ppc_wakeup(); - } else { - impl.atomic_cancel_ext_exception(); - } + if (using_pearpc()) { + if (active) { + impl.atomic_raise_ext_exception(); + uae_ppc_wakeup(); + } else { + impl.atomic_cancel_ext_exception(); + } + return; + } + + PPCLockStatus status = get_ppc_lock(PPC_KEEP_SPINLOCK); + impl.external_interrupt(active); + release_ppc_lock(status); } // sleep until interrupt (or PPC stopped)