#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;
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;
uae_u32 realstart = start;
addrbank *orig_bank = NULL;
+ bank->flags |= ABFLAG_MAPPED;
+
#ifdef WITH_THREADED_CPU
if (currprefs.cpu_thread) {
addrbank *b = bank;
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);
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)
#ifdef WITH_PPC
if (state)
uae_ppc_spinlock_get();
-#endif
-#ifdef WITH_THREADED_CPU
- cpu_semaphore_get();
#endif
return ret;
}
#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 <glib.h>
-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
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) {
}
#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 */
#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;
}
bool exit = false;
struct regstruct *r = ®s;
+ cpu_thread_tid = uae_thread_get_id();
+
cpu_thread_active = 1;
while (!exit) {
TRY(prb)
(*cpufunctbl[r->opcode])(r->opcode);
- if (r->spcflags) {
+ if (regs.spcflags || cpu_thread_ilvl > 0) {
if (do_specialties_thread())
exit = true;
}
+
}
} CATCH(prb)
{
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;
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;
// 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);
}