From: Toni Wilen Date: Tue, 14 Aug 2018 18:55:56 +0000 (+0300) Subject: Still useless threaded CPU emulation. X-Git-Tag: 4100~127 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=d9417741897afe2e6993566d5cac34f6c0305fdf;p=francis%2Fwinuae.git Still useless threaded CPU emulation. --- diff --git a/include/newcpu.h b/include/newcpu.h index 7cdb4cf8..0e2cc30c 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -797,8 +797,6 @@ extern bool can_cpu_tracer (void); #define CPU_HALT_SSP_IN_NON_EXISTING_ADDRESS 10 #define CPU_HALT_INVALID_START_ADDRESS 11 -void cpu_semaphore_get(void); -void cpu_semaphore_release(void); bool execute_other_cpu(int until); void execute_other_cpu_single(void); diff --git a/memory.cpp b/memory.cpp index 5129f3bc..2d184a4e 100644 --- a/memory.cpp +++ b/memory.cpp @@ -2893,54 +2893,55 @@ struct addrbank_thread { #define MAX_THREAD_BANKS 200 static addrbank_thread *thread_banks[MAX_THREAD_BANKS]; -static addrbank *thread_mem_banks[MEMORY_BANKS]; +addrbank *thread_mem_banks[MEMORY_BANKS]; static int thread_banks_used; static void REGPARAM2 threadcpu_lput(uaecptr addr, uae_u32 l) { - cpu_semaphore_get(); - thread_mem_banks[bankindex(addr)]->lput(addr, l); - cpu_semaphore_release(); -} + //write_log(_T("LPUT %08x %08x %08x\n"), addr, l, M68K_GETPC); + process_cpu_indirect_memory_write(addr, l, 2); +} static void REGPARAM2 threadcpu_wput(uaecptr addr, uae_u32 w) { - cpu_semaphore_get(); - thread_mem_banks[bankindex(addr)]->wput(addr, w); - cpu_semaphore_release(); -} + //write_log(_T("WPUT %08x %08x %08x\n"), addr, w, M68K_GETPC); + process_cpu_indirect_memory_write(addr, w, 1); +} static void REGPARAM2 threadcpu_bput(uaecptr addr, uae_u32 b) { - cpu_semaphore_get(); - thread_mem_banks[bankindex(addr)]->bput(addr, b); - cpu_semaphore_release(); + //write_log(_T("BPUT %08x %08x %08x\n"), addr, b, M68K_GETPC); + + process_cpu_indirect_memory_write(addr, b, 0); } static uae_u32 REGPARAM2 threadcpu_lget(uaecptr addr) { - cpu_semaphore_get(); - uae_u32 v = thread_mem_banks[bankindex(addr)]->lget(addr); - cpu_semaphore_release(); + uae_u32 v = process_cpu_indirect_memory_read(addr, 2); + + //write_log(_T("LGET %08x %08x %08x\n"), addr, v, M68K_GETPC); + return v; } static uae_u32 REGPARAM2 threadcpu_wget(uaecptr addr) { - cpu_semaphore_get(); - uae_u32 v = thread_mem_banks[bankindex(addr)]->wget(addr); - cpu_semaphore_release(); + uae_u32 v = process_cpu_indirect_memory_read(addr, 1); + + //write_log(_T("WGET %08x %08x %08x\n"), addr, v, M68K_GETPC); + return v; } uae_u32 REGPARAM2 threadcpu_bget(uaecptr addr) { - cpu_semaphore_get(); - uae_u32 v = thread_mem_banks[bankindex(addr)]->bget(addr); - cpu_semaphore_release(); + uae_u32 v = process_cpu_indirect_memory_read(addr, 0); + + //write_log(_T("BGET %08x %08x %08x\n"), addr, v, M68K_GETPC); + return v; } static addrbank *get_bank_cpu_thread(addrbank *bank) { - if (bank->flags & ABFLAG_THREADSAFE) + if ((bank->flags & ABFLAG_THREADSAFE) && !(bank->flags & ABFLAG_IO)) return bank; if (bank == &dummy_bank) return bank; @@ -2957,6 +2958,8 @@ static addrbank *get_bank_cpu_thread(addrbank *bank) at->orig = bank; memcpy(&at->ab, bank, sizeof addrbank); addrbank *tb = &at->ab; + tb->jit_read_flag = S_READ; + tb->jit_write_flag = S_WRITE; tb->lget = threadcpu_lget; tb->wget = threadcpu_wget; tb->bget = threadcpu_bget; @@ -2975,6 +2978,8 @@ static void map_banks2 (addrbank *bank, int start, int size, int realsize, int q uae_u32 realstart = start; addrbank *orig_bank = NULL; + bank->flags |= ABFLAG_MAPPED; + #ifdef WITH_THREADED_CPU if (currprefs.cpu_thread) { addrbank *b = bank; @@ -2987,7 +2992,6 @@ static void map_banks2 (addrbank *bank, int start, int size, int realsize, int q if (quick <= 0) old = debug_bankchange (-1); flush_icache_hard (3); /* Sure don't want to keep any old mappings around! */ - bank->flags |= ABFLAG_MAPPED; #ifdef NATMEM_OFFSET if (!quick) delete_shmmaps (start << 16, size << 16); diff --git a/newcpu.cpp b/newcpu.cpp index 12846edf..8a65e208 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -4490,9 +4490,6 @@ bool execute_other_cpu(int until) int cpu_sleep_millis(int ms) { int ret = 0; -#ifdef WITH_THREADED_CPU - cpu_semaphore_release(); -#endif #ifdef WITH_PPC int state = ppc_state; if (state) @@ -4508,9 +4505,6 @@ int cpu_sleep_millis(int ms) #ifdef WITH_PPC if (state) uae_ppc_spinlock_get(); -#endif -#ifdef WITH_THREADED_CPU - cpu_semaphore_get(); #endif return ret; } @@ -5210,45 +5204,34 @@ static uae_u16 get_word_020_prefetchf (uae_u32 pc) #ifdef WITH_THREADED_CPU static volatile int cpu_thread_active; +static uae_sem_t cpu_in_sema, cpu_out_sema, cpu_wakeup_sema; + +static volatile int cpu_thread_ilvl; +static volatile uae_u32 cpu_thread_indirect_mode; +static volatile uae_u32 cpu_thread_indirect_addr; +static volatile uae_u32 cpu_thread_indirect_val; +static volatile uae_u32 cpu_thread_indirect_size; +static volatile uae_u32 cpu_thread_reset; +static uae_thread_id cpu_thread_tid; -#define SPINLOCK_DEBUG 0 -static volatile int m68k_spinlock_cnt; -static volatile long m68k_spinlock_waiting; -#ifdef _WIN32 -#define CRITICAL_SECTION_SPIN_COUNT 5000 -static CRITICAL_SECTION m68k_cs1; static bool m68k_cs_initialized; -static DWORD m68k_cs_owner; -#else -#include -static GMutex mutex; -#endif + +void custom_reset_cpu(bool hardreset, bool keyboardreset) +{ + if (cpu_thread_tid != uae_thread_get_id()) { + custom_reset(hardreset, keyboardreset); + return; + } + cpu_thread_reset = 1 | (hardreset ? 2 : 0) | (keyboardreset ? 4 : 0); + uae_sem_post(&cpu_wakeup_sema); + uae_sem_wait(&cpu_in_sema); +} static int do_specialties_thread(void) { if (regs.spcflags & SPCFLAG_MODE_CHANGE) return 1; - if (regs.spcflags & SPCFLAG_CHECK) { - if (regs.halted) { - if (haltloop()) - return 1; - } - if (m68k_reset_delay) { - int vsynccnt = 60; - int vsyncstate = -1; - while (vsynccnt > 0) { - int vp = vpos; - while (vp == vpos) { - sleep_millis(1); - } - vsynccnt--; - } - } - m68k_reset_delay = 0; - unset_special(SPCFLAG_CHECK); - } - #ifdef JIT unset_special(SPCFLAG_END_COMPILE); /* has done its job */ #endif @@ -5260,146 +5243,190 @@ static int do_specialties_thread(void) unset_special(SPCFLAG_TRAP); Exception(3); } - bool first = true; - while ((regs.spcflags & SPCFLAG_STOP) && !(regs.spcflags & SPCFLAG_BRK)) { - if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) { - int intr = intlev(); - unset_special(SPCFLAG_INT | SPCFLAG_DOINT); - if (intr > 0 && intr > regs.intmask) - do_interrupt(intr); - } - - if (regs.spcflags & SPCFLAG_MODE_CHANGE) { - m68k_resumestopped(); - return 1; - } - } if (regs.spcflags & SPCFLAG_TRACE) do_trace(); - if (regs.spcflags & SPCFLAG_INT) { - int intr = intlev(); - unset_special(SPCFLAG_INT | SPCFLAG_DOINT); - if (intr > 0 && (intr > regs.intmask || intr == 7)) - do_interrupt(intr); - } + for (;;) { - if (regs.spcflags & SPCFLAG_DOINT) { - unset_special(SPCFLAG_DOINT); - set_special(SPCFLAG_INT); - } + if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) { + return 1; + } - if (regs.spcflags & SPCFLAG_BRK) { - return 1; + int ilvl = cpu_thread_ilvl; + if (ilvl > 0 && (ilvl > regs.intmask || ilvl == 7)) { + do_interrupt(ilvl); + } + + if (!(regs.spcflags & SPCFLAG_STOP)) + break; + + uae_sem_wait(&cpu_wakeup_sema); } return 0; } -void cpu_semaphore_get(void) +static void init_cpu_thread(void) { if (!currprefs.cpu_thread) return; - DWORD tid = GetCurrentThreadId(); - - if (tid == m68k_cs_owner) { - m68k_spinlock_cnt++; + if (m68k_cs_initialized) return; - } - -#ifdef _WIN32 - _InterlockedIncrement(&m68k_spinlock_waiting); - EnterCriticalSection(&m68k_cs1); - _InterlockedDecrement(&m68k_spinlock_waiting); - m68k_cs_owner = tid; - m68k_spinlock_cnt++; -#else - g_mutex_lock(&mutex); // FIXME -#endif + uae_sem_init(&cpu_in_sema, 0, 0); + uae_sem_init(&cpu_out_sema, 0, 0); + uae_sem_init(&cpu_wakeup_sema, 0, 0); + m68k_cs_initialized = true; } -void cpu_semaphore_release(void) + +extern addrbank *thread_mem_banks[MEMORY_BANKS]; + +uae_u32 process_cpu_indirect_memory_read(uae_u32 addr, int size) { - if (!currprefs.cpu_thread) - return; -#ifdef _WIN32 - m68k_spinlock_cnt--; - if (m68k_spinlock_cnt == 0) { - m68k_cs_owner = 0; - LeaveCriticalSection(&m68k_cs1); + // Do direct access if call is from filesystem etc thread + if (cpu_thread_tid != uae_thread_get_id()) { + uae_u32 data = 0; + addrbank *ab = thread_mem_banks[bankindex(addr)]; + switch (size) + { + case 0: + data = ab->bget(addr) & 0xff; + break; + case 1: + data = ab->wget(addr) & 0xffff; + break; + case 2: + data = ab->lget(addr); + break; + } + return data; } -#else - g_mutex_unlock(&mutex); // FIXME -#endif + + cpu_thread_indirect_mode = 2; + cpu_thread_indirect_addr = addr; + cpu_thread_indirect_size = size; + uae_sem_post(&cpu_out_sema); + uae_sem_wait(&cpu_in_sema); + cpu_thread_indirect_mode = 0xfe; + return cpu_thread_indirect_val; } -static void init_cpu_thread(void) +void process_cpu_indirect_memory_write(uae_u32 addr, uae_u32 data, int size) { - if (!currprefs.cpu_thread) + if (cpu_thread_tid != uae_thread_get_id()) { + addrbank *ab = thread_mem_banks[bankindex(addr)]; + switch (size) + { + case 0: + ab->bput(addr, data & 0xff); + break; + case 1: + ab->wput(addr, data & 0xffff); + break; + case 2: + ab->lput(addr, data); + break; + } return; -#ifdef _WIN32 - if (m68k_cs_initialized) { - DeleteCriticalSection(&m68k_cs1); } - InitializeCriticalSectionAndSpinCount(&m68k_cs1, CRITICAL_SECTION_SPIN_COUNT); -#endif + cpu_thread_indirect_mode = 1; + cpu_thread_indirect_addr = addr; + cpu_thread_indirect_size = size; + cpu_thread_indirect_val = data; + uae_sem_post(&cpu_out_sema); + uae_sem_wait(&cpu_in_sema); + cpu_thread_indirect_mode = 0xff; } static void run_cpu_thread(void *(*f)(void *)) { + int framecnt = -1; + int vp = 0; + int intlev_prev = 0; + cpu_thread_active = 0; -#if SPINLOCK_DEBUG - m68k_spinlock_cnt = 0; -#endif - m68k_cs_initialized = true; - if (uae_start_thread(_T("cpu"), f, NULL, NULL)) { - while (!cpu_thread_active) { - sleep_millis(1); - } - while (!(regs.spcflags & SPCFLAG_MODE_CHANGE)) { - - cpu_semaphore_get(); - frame_time_t c = read_processor_time(); - while (cpu_thread_active) { - int vsynctimeperline = vsynctimebase / (maxvpos_display + 1); - - int vp = vpos; - while ((int)read_processor_time() - (int)c > -vsynctimebase / 10) { - if (vp != vpos) { - vp = vpos; - if (vpos + 1 == maxvpos + lof_store) { - c = read_processor_time(); - } - c += vsynctimeperline; - } - cycles_do_special(); - do_cycles(maxhpos / 2 * CYCLE_UNIT); - if (regs.spcflags & SPCFLAG_COPPER) { - do_copper(); - } - check_uae_int_request(); - int w = m68k_spinlock_waiting; - if (w) { - cpu_semaphore_release(); - while (m68k_spinlock_waiting == w); - cpu_semaphore_get(); + uae_sem_init(&cpu_in_sema, 0, 0); + uae_sem_init(&cpu_out_sema, 0, 0); + uae_sem_init(&cpu_wakeup_sema, 0, 0); + + if (!uae_start_thread(_T("cpu"), f, NULL, NULL)) + return; + while (!cpu_thread_active) { + sleep_millis(1); + } + + while (!(regs.spcflags & SPCFLAG_MODE_CHANGE)) { + int maxperloop = 10; + + while (!uae_sem_trywait(&cpu_out_sema)) { + uae_u32 cmd, addr, data, size, mode; + + addr = cpu_thread_indirect_addr; + data = cpu_thread_indirect_val; + size = cpu_thread_indirect_size; + mode = cpu_thread_indirect_mode; + + switch(mode) + { + case 1: + { + addrbank *ab = thread_mem_banks[bankindex(addr)]; + switch (size) + { + case 0: + ab->bput(addr, data & 0xff); + break; + case 1: + ab->wput(addr, data & 0xffff); + break; + case 2: + ab->lput(addr, data); + break; } + uae_sem_post(&cpu_in_sema); + break; } - cpu_semaphore_release(); - sleep_millis(1); - cpu_semaphore_get(); - while ((int)read_processor_time() - (int)c < 0) { - check_uae_int_request(); - int w = m68k_spinlock_waiting; - if (w) { - cpu_semaphore_release(); - while (m68k_spinlock_waiting == w); - cpu_semaphore_get(); + case 2: + { + addrbank *ab = thread_mem_banks[bankindex(addr)]; + switch (size) + { + case 0: + data = ab->bget(addr) & 0xff; + break; + case 1: + data = ab->wget(addr) & 0xffff; + break; + case 2: + data = ab->lget(addr); + break; } + cpu_thread_indirect_val = data; + uae_sem_post(&cpu_in_sema); + break; } + default: + write_log(_T("cpu_thread_indirect_mode=%08x!\n"), mode); + break; } - cpu_semaphore_release(); + if (maxperloop-- < 0) + break; + } + + if (framecnt != timeframes) { + framecnt = timeframes; + } + + if (cpu_thread_reset) { + bool hardreset = cpu_thread_reset & 2; + bool keyboardreset = cpu_thread_reset & 4; + custom_reset(hardreset, keyboardreset); + cpu_thread_reset = 0; + uae_sem_post(&cpu_in_sema); + } + + if (regs.spcflags & SPCFLAG_BRK) { unset_special(SPCFLAG_BRK); #ifdef DEBUGGER if (debugging) { @@ -5407,8 +5434,47 @@ static void run_cpu_thread(void *(*f)(void *)) } #endif } + + if (vp == vpos) { + + do_cycles((maxhpos / 2) * CYCLE_UNIT); + + if (regs.spcflags & SPCFLAG_COPPER) { + do_copper(); + } + + check_uae_int_request(); + if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) { + int intr = intlev(); + unset_special(SPCFLAG_INT | SPCFLAG_DOINT); + if (intr > 0) { + cpu_thread_ilvl = intr; + cycles_do_special(); + uae_sem_post(&cpu_wakeup_sema); + } else { + cpu_thread_ilvl = 0; + } + } + continue; + } + + frame_time_t next = vsyncmintimepre + (vsynctimebase * vpos / (maxvpos + 1)); + frame_time_t c = read_processor_time(); + if ((int)next - (int)c > 0 && (int)next - (int)c < vsyncmaxtime * 2) + continue; + + vp = vpos; + } + + while (cpu_thread_active) { + uae_sem_post(&cpu_in_sema); + uae_sem_post(&cpu_wakeup_sema); + sleep_millis(1); + } + } + #endif #ifdef JIT /* Completely different run_2 replacement */ @@ -5503,16 +5569,32 @@ typedef void compiled_handler (void); #ifdef WITH_THREADED_CPU static void *cpu_thread_run_jit(void *v) { + cpu_thread_tid = uae_thread_get_id(); cpu_thread_active = 1; - for (;;) { - ((compiled_handler*)(pushall_call_handler))(); - /* Whenever we return from that, we should check spcflags */ - if (regs.spcflags) { - if (do_specialties_thread()) { - break; +#ifdef USE_STRUCTURED_EXCEPTION_HANDLING + __try +#endif + { + for (;;) { + ((compiled_handler*)(pushall_call_handler))(); + /* Whenever we return from that, we should check spcflags */ + if (regs.spcflags || cpu_thread_ilvl > 0) { + if (do_specialties_thread()) { + break; + } } } } +#ifdef USE_STRUCTURED_EXCEPTION_HANDLING +#ifdef JIT + __except (EvalException(GetExceptionInformation())) +#else + __except (DummyException(GetExceptionInformation(), GetExceptionCode())) +#endif + { + // EvalException does the good stuff... + } +#endif cpu_thread_active = 0; return 0; } @@ -6217,6 +6299,8 @@ static void *cpu_thread_run_2(void *v) bool exit = false; struct regstruct *r = ®s; + cpu_thread_tid = uae_thread_get_id(); + cpu_thread_active = 1; while (!exit) { TRY(prb) @@ -6228,10 +6312,11 @@ static void *cpu_thread_run_2(void *v) (*cpufunctbl[r->opcode])(r->opcode); - if (r->spcflags) { + if (regs.spcflags || cpu_thread_ilvl > 0) { if (do_specialties_thread()) exit = true; } + } } CATCH(prb) { @@ -8792,7 +8877,7 @@ void cpureset (void) set_special(SPCFLAG_CHECK); send_internalevent(INTERNALEVENT_CPURESET); if ((currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact) && currprefs.cpu_model <= 68020) { - custom_reset (false, false); + custom_reset_cpu(false, false); return; } pc = m68k_getpc () + 2; @@ -8800,7 +8885,7 @@ void cpureset (void) if (ab->check (pc, 2)) { write_log (_T("CPU reset PC=%x (%s)..\n"), pc - 2, ab->name); ins = get_word (pc); - custom_reset (false, false); + custom_reset_cpu(false, false); // did memory disappear under us? if (ab == &get_mem_bank (pc)) return; @@ -8818,7 +8903,7 @@ void cpureset (void) // the best we can do, jump directly to ROM entrypoint // (which is probably what program wanted anyway) write_log (_T("CPU Reset PC=%x (%s), invalid memory -> %x.\n"), pc, ab->name, ksboot + 2); - custom_reset (false, false); + custom_reset_cpu(false, false); m68k_setpc_normal (ksboot); } diff --git a/od-win32/machdep/maccess.h b/od-win32/machdep/maccess.h index fc1bc7a9..2a5223f7 100644 --- a/od-win32/machdep/maccess.h +++ b/od-win32/machdep/maccess.h @@ -13,6 +13,11 @@ #define ALIGN_POINTER_TO32(p) ((~(unsigned long)(p)) & 3) +STATIC_INLINE uae_u64 do_get_mem_quad(uae_u64 *a) +{ + return _byteswap_uint64(*a); +} + STATIC_INLINE uae_u32 do_get_mem_long(uae_u32 *a) { return _byteswap_ulong(*a); @@ -25,6 +30,11 @@ STATIC_INLINE uae_u16 do_get_mem_word(uae_u16 *a) #define do_get_mem_byte(a) ((uae_u32)*(uae_u8 *)(a)) +STATIC_INLINE void do_put_mem_quad(uae_u64 *a, uae_u64 v) +{ + *a = _byteswap_uint64(v); +} + STATIC_INLINE void do_put_mem_long(uae_u32 *a, uae_u32 v) { *a = _byteswap_ulong(v); diff --git a/od-win32/posixemu.cpp b/od-win32/posixemu.cpp index db9380de..43dead3c 100644 --- a/od-win32/posixemu.cpp +++ b/od-win32/posixemu.cpp @@ -138,6 +138,11 @@ void uae_sem_destroy (uae_sem_t * event) } } +uae_thread_id uae_thread_get_id(void) +{ + return (uae_thread_id)GetCurrentThreadId(); +} + #ifndef _CONSOLE typedef unsigned (__stdcall *BEGINTHREADEX_FUNCPTR)(void *); diff --git a/od-win32/sysconfig.h b/od-win32/sysconfig.h index 74d42a1a..ef2692b3 100644 --- a/od-win32/sysconfig.h +++ b/od-win32/sysconfig.h @@ -102,6 +102,8 @@ #define WITH_TOCCATA #define WITH_PCI #define WITH_X86 +#define WITH_THREADED_CPU + #else diff --git a/od-win32/threaddep/thread.h b/od-win32/threaddep/thread.h index 545df235..4df8a22c 100644 --- a/od-win32/threaddep/thread.h +++ b/od-win32/threaddep/thread.h @@ -11,6 +11,7 @@ extern int uae_start_thread(const TCHAR *name, void *(*f)(void *), void *arg, ua extern int uae_start_thread_fast(void *(*f)(void *), void *arg, uae_thread_id *thread); extern void uae_end_thread(uae_thread_id *thread); extern void uae_set_thread_priority(uae_thread_id *, int); +extern uae_thread_id uae_thread_get_id(void); #include "commpipe.h" diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index 0d8abb65..b1b7fc11 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -507,13 +507,7 @@ int sleep_millis (int ms) int sleep_millis_amiga(int ms) { -#ifdef WITH_THREADED_CPU - cpu_semaphore_release(); -#endif int ret = sleep_millis_main(ms); -#ifdef WITH_THREADED_CPU - cpu_semaphore_get(); -#endif return ret; }