--- previous/src/dimension/i860.cpp 2018/04/24 19:30:01 1.1 +++ previous/src/dimension/i860.cpp 2018/04/24 19:31:34 1.1.1.2 @@ -15,69 +15,54 @@ ***************************************************************************/ -#include -#include -#include -#include -#include #include "i860.hpp" static i860_cpu_device nd_i860; extern "C" { + + static void i860_run_nop(int nHostCycles) {} + + i860_run_func i860_Run = i860_run_nop; + + static void i860_run_thread(int nHostCycles) { + nd_nbic_interrupt(); + } + + static void i860_run_no_thread(int nHostCycles) { + nd_i860.handle_msgs(); + + if(nd_i860.is_halted()) return; + + nHostCycles *= 33; // i860 @ 33MHz + nHostCycles /= ConfigureParams.System.nCpuFreq; + while (nHostCycles > 0) { + nd_i860.run_cycle(); + nHostCycles -= 2; + } + + nd_nbic_interrupt(); + } + void nd_i860_init() { + i860_Run = ConfigureParams.Dimension.bI860Thread ? i860_run_thread : i860_run_no_thread; nd_i860.init(); } void nd_i860_uninit() { nd_i860.uninit(); } - - int nd_speed_hack; - - void nd_set_speed_hack(int state) { - nd_speed_hack = state; - } + void nd_i860_pause(bool state) { + nd_i860.pause(state); + } + void nd_start_debugger(void) { nd_i860.send_msg(MSG_DBG_BREAK); } - - static int checklock_cnt = 0; - void i860_Run(int nHostCycles) { -#if ENABLE_PERF_COUNTERS - nd_i860.m_m68k_cylces += nHostCycles; -#endif -#if ENABLE_I860_THREAD - if(nd_speed_hack) { - // while spped-hack is on, slow down m68k a bit - for(int i = 10; --i >= 0;) - checklock(&nd_i860.m_debugger_lock); - } - if(checklock_cnt <= 0) { - checklock(&nd_i860.m_debugger_lock); - // optimzation: check the debugger lock only all 10000 cycles - checklock_cnt = 10000; - } - else - checklock_cnt -= nHostCycles; -#else - nd_i860.handle_msgs(); - - if(nd_i860.is_halted()) return; - - if (nd_speed_hack) { - while(nHostCycles) { - nd_i860.run_cycle(); - nHostCycles -= 2; - } - } else - nd_i860.run_cycle(); -#endif - nd_nbic_interrupt(); - } int i860_thread(void* data) { + SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW); ((i860_cpu_device*)data)->run(); return 0; } @@ -85,20 +70,41 @@ extern "C" { void i860_reset() { nd_i860.send_msg(MSG_I860_RESET); } + + void nd_display_blank() { + nd_i860.send_msg(MSG_DISPLAY_BLANK); + } + + void nd_video_blank() { + nd_i860.send_msg(MSG_VIDEO_BLANK); + } + + void i860_interrupt() { + nd_i860.interrupt(); + } - void i860_tick(bool intr) { - nd_i860.tick(intr); + const char* nd_reports(double realTime, double hostTime) { + return nd_i860.reports(realTime, hostTime); } } i860_cpu_device::i860_cpu_device() { -#if ENABLE_I860_THREAD m_thread = NULL; -#endif -#if ENABLE_PERF_COUNTERS - dump_reset_perfc(); -#endif - m_halt = true; + m_halt = true; + + for(int i = 0; i < 8192; i++) { + int upper6 = i >> 7; + switch (upper6) { + case 0x12: + decoder_tbl[i] = fp_decode_tbl[i & 0x7f]; + break; + case 0x13: + decoder_tbl[i] = core_esc_decode_tbl[i&3]; + break; + default: + decoder_tbl[i] = decode_tbl[upper6]; + } + } } void i860_cpu_device::set_mem_access(bool be) { @@ -142,22 +148,22 @@ inline void i860_cpu_device::set_iregval m_iregs[0] = 0; // make sure r0 is always 0 } -inline float i860_cpu_device::get_fregval_s (int fr) { - return *(float*)(&m_fregs[fr * 4]); +inline FLOAT32 i860_cpu_device::get_fregval_s (int fr) { + return *(FLOAT32*)(&m_fregs[fr * 4]); } -inline void i860_cpu_device::set_fregval_s (int fr, float s) { +inline void i860_cpu_device::set_fregval_s (int fr, FLOAT32 s) { if(fr > 1) - *(float*)(&m_fregs[fr * 4]) = s; + *(FLOAT32*)(&m_fregs[fr * 4]) = s; } -inline double i860_cpu_device::get_fregval_d (int fr) { - return *(double*)(&m_fregs[fr * 4]); +inline FLOAT64 i860_cpu_device::get_fregval_d (int fr) { + return *(FLOAT64*)(&m_fregs[fr * 4]); } -inline void i860_cpu_device::set_fregval_d (int fr, double d) { +inline void i860_cpu_device::set_fregval_d (int fr, FLOAT64 d) { if(fr > 1) - *(double*)(&m_fregs[fr * 4]) = d; + *(FLOAT64*)(&m_fregs[fr * 4]) = d; } inline void i860_cpu_device::SET_PSR_CC(int val) { @@ -166,9 +172,9 @@ inline void i860_cpu_device::SET_PSR_CC( } void i860_cpu_device::send_msg(int msg) { - lock(&m_port_lock); + host_lock(&m_port_lock); m_port |= msg; - unlock(&m_port_lock); + host_unlock(&m_port_lock); } void i860_cpu_device::handle_trap(UINT32 savepc) { @@ -408,10 +414,10 @@ int i860_cpu_device::memtest(bool be) { rdmem[4](P_TEST_ADDR+0, &tmp32); if(tmp32 != 0x01234567) return err+4; UINT8* uint8p = (UINT8*)&uint64; - set_fregval_d(2, *((double*)uint8p)); + set_fregval_d(2, *((FLOAT64*)uint8p)); writemem_emu(P_TEST_ADDR, 8, &m_fregs[8], 0xff); readmem_emu (P_TEST_ADDR, 8, &m_fregs[8]); - *((double*)&uint64) = get_fregval_d(2); + *((FLOAT64*)&uint64) = get_fregval_d(2); if(uint64 != 0x0123456789ABCDEFLL) return err+5; UINT32 lo; @@ -433,7 +439,9 @@ void i860_cpu_device::init() { CFGS[CONF_I860_SPEED] = CONF_STR(CONF_I860_SPEED); CFGS[CONF_I860_DEV] = CONF_STR(CONF_I860_DEV); CFGS[CONF_I860_NO_THREAD] = CONF_STR(CONF_I860_NO_THREAD); - Log_Printf(LOG_WARN, "[i860] Emulator configured for %s", CFGS[CONF_I860]); + Log_Printf(LOG_WARN, "[i860] Emulator configured for %s, %d logical cores detected, %s", + CFGS[CONF_I860], host_num_cpus(), + ConfigureParams.Dimension.bI860Thread ? "using seperate thread for i860" : "i860 running on m68k thread. WARNING: expect slow emulation"); m_single_stepping = 0; m_lastcmd = 0; @@ -441,7 +449,7 @@ void i860_cpu_device::init() { m_break_on_next_msg = false; m_dim = DIM_NONE; m_traceback_idx = 0; - + set_mem_access(false); // some sanity checks for endianess @@ -456,13 +464,13 @@ void i860_cpu_device::init() { for(int i = 0; i < 32; i++) { uint8p[3] = i; - set_fregval_s(i, *((float*)uint8p)); + set_fregval_s(i, *((FLOAT32*)uint8p)); } if(get_fregval_s(0) != 0) {err = 198; goto error;} if(get_fregval_s(1) != 0) {err = 199; goto error;} for(int i = 2; i < 32; i++) { uint8p[3] = i; - if(get_fregval_s(i) != *((float*)uint8p)) + if(get_fregval_s(i) != *((FLOAT32*)uint8p)) {err = 100+i; goto error;} } for(int i = 2; i < 32; i++) { @@ -487,18 +495,18 @@ void i860_cpu_device::init() { for(int i = 0; i < 16; i++) { uint8p[7] = i; - set_fregval_d(i*2, *((double*)uint8p)); + set_fregval_d(i*2, *((FLOAT64*)uint8p)); } if(get_fregval_d(0) != 0) {err = 10199; goto error;} for(int i = 1; i < 16; i++) { uint8p[7] = i; - if(get_fregval_d(i*2) != *((double*)uint8p)) + if(get_fregval_d(i*2) != *((FLOAT64*)uint8p)) {err = 10100+i; goto error;} } for(int i = 2; i < 32; i += 2) { - float hi = get_fregval_s(i+1); - float lo = get_fregval_s(i+0); + FLOAT32 hi = get_fregval_s(i+1); + FLOAT32 lo = get_fregval_s(i+0); if((*(UINT32*)&hi) != (0x00234567 | (i<<23))) {err = 10100+i; goto error;} if((*(UINT32*)&lo) != 0x89ABCDEF) {err = 10100+i; goto error;} } @@ -525,38 +533,39 @@ error: } send_msg(MSG_I860_RESET); -#if ENABLE_I860_THREAD - m_thread = thread_create(i860_thread, this); -#endif + if(ConfigureParams.Dimension.bI860Thread) + m_thread = host_thread_create(i860_thread, this); } void i860_cpu_device::uninit() { - if(is_halted()) return; - halt(true); - send_msg(MSG_I860_KILL); -#if ENABLE_I860_THREAD + if(m_thread) { - thread_wait(m_thread); + send_msg(MSG_I860_KILL); + host_thread_wait(m_thread); m_thread = NULL; } send_msg(MSG_NONE); -#endif } /* Message disaptcher - executed on i860 thread, safe to call i860 methods */ bool i860_cpu_device::handle_msgs() { - lock(&m_port_lock); + host_lock(&m_port_lock); int msg = m_port; m_port = 0; - unlock(&m_port_lock); + host_unlock(&m_port_lock); if(msg & MSG_I860_KILL) return false; + if(msg & MSG_I860_RESET) reset(); else if(msg & MSG_INTR) intr(); + if(msg & MSG_DISPLAY_BLANK) + nd_set_blank_state(ND_DISPLAY, host_blank_state(ND_SLOT, ND_DISPLAY)); + if(msg & MSG_VIDEO_BLANK) + nd_set_blank_state(ND_VIDEO, host_blank_state(ND_SLOT, ND_VIDEO)); if(msg & MSG_DBG_BREAK) debugger('d', "BREAK at pc=%08X", m_pc); return true; @@ -567,64 +576,51 @@ void i860_cpu_device::run() { /* Sleep a bit if halted */ if(is_halted()) { - sleep_ms(100); + host_sleep_ms(100); continue; } /* Run some i860 cycles before re-checking messages*/ - for(int i = 10; --i >= 0;) + for(int i = 16; --i >= 0;) run_cycle(); } } -void i860_cpu_device::tick(bool intr) { - if(intr) send_msg(MSG_INTR); -#if ENABLE_PERF_COUNTERS - UINT32 now = time_ms(); - m_time_delta_ms += now - m_abs_time_ms; - m_abs_time_ms = now; - if(m_time_delta_ms > 5000) - dump_reset_perfc(); -#endif +void i860_cpu_device::interrupt() { + send_msg(MSG_INTR); } -#if ENABLE_PERF_COUNTERS -void i860_cpu_device::dump_reset_perfc() { - static bool dump = false; - if(dump) { - UINT32 dt = m_time_delta_ms; - if(dt) { - if(trylock(&m_debugger_lock)) { - Log_Printf(LOG_WARN, "[i860] Stats: MIPS=%lld.%lld icache_hit=%lld%% tlb_hit=%lld%% icach_inval/s=%lld tlb_inval/s=%lld intr/s=%lld", - (m_insn_decoded / (dt * 100)) / 10, (m_insn_decoded / (dt * 100)) % 10, - m_icache_hit+m_icache_miss == 0 ? 0 : (100 * m_icache_hit) / (m_icache_hit+m_icache_miss) , - m_tlb_hit+m_tlb_miss == 0 ? 0 : (100 * m_tlb_hit) / (m_tlb_hit+m_tlb_miss), - (1000*m_icache_inval)/dt, - (1000*m_tlb_inval)/dt, - (1000*m_intrs)/dt - ); - Log_Printf(LOG_WARN, "[m68k] Stats: Mcycles/s=%lld.%lld", - (m_m68k_cylces / (dt * 100)) / 10, (m_insn_decoded / (dt * 100)) % 10); - - m_m68k_cylces = 0; - m_insn_decoded = 0; - m_icache_hit = 0; - m_icache_miss = 0; - m_icache_inval = 0; - m_tlb_hit = 0; - m_tlb_miss = 0; - m_tlb_inval = 0; - m_time_delta_ms = 0; - m_intrs = 0; +const char* i860_cpu_device::reports(double realTime, double hostTime) { + double dVT = hostTime - m_last_vt; + + if(is_halted()) { + m_report[0] = 0; + } else { + if(dVT == 0) dVT = 0.0001; + sprintf(m_report, "i860:{MIPS=%.1f icache_hit=%lld%% tlb_hit=%lld%% icach_inval/s=%.0f tlb_inval/s=%.0f intr/s=%0.f}", + (m_insn_decoded / (dVT*1000*1000)), + m_icache_hit+m_icache_miss == 0 ? 0 : (100 * m_icache_hit) / (m_icache_hit+m_icache_miss) , + m_tlb_hit+m_tlb_miss == 0 ? 0 : (100 * m_tlb_hit) / (m_tlb_hit+m_tlb_miss), + (m_icache_inval)/dVT, + (m_tlb_inval)/dVT, + (m_intrs)/dVT + ); + + m_insn_decoded = 0; + m_icache_hit = 0; + m_icache_miss = 0; + m_icache_inval = 0; + m_tlb_hit = 0; + m_tlb_miss = 0; + m_tlb_inval = 0; + m_intrs = 0; - unlock(&m_debugger_lock); - } - } + m_last_rt = realTime; + m_last_vt = hostTime; } - dump = true; + return m_report; } -#endif offs_t i860_cpu_device::disasm(char* buffer, offs_t pc) { return pc + i860_disassembler(pc, ifetch_notrap(pc), buffer);