#ifdef DEBUG_JIT #include "debug_rsp.hpp" #else #include "rsp_jit.hpp" #endif #include #include #include "m64p_plugin.h" #include "rsp_1.1.h" #define RSP_PARALLEL_VERSION 0x0101 #define RSP_PLUGIN_API_VERSION 0x020000 static void (*l_DebugCallback)(void *, int, const char *) = NULL; static void *l_DebugCallContext = NULL; #define ATTR_FMT(fmtpos, attrpos) __attribute__ ((format (printf, fmtpos, attrpos))) static void DebugMessage(int level, const char *message, ...) ATTR_FMT(2, 3); void DebugMessage(int level, const char *message, ...) { char msgbuf[1024]; va_list args; if (l_DebugCallback == NULL) return; va_start(args, message); vsprintf(msgbuf, message, args); (*l_DebugCallback)(l_DebugCallContext, level, msgbuf); va_end(args); } namespace RSP { RSP_INFO rsp; #ifdef DEBUG_JIT RSP::CPU cpu; #else RSP::JIT::CPU cpu; #endif } // namespace RSP extern "C" { // Hack entry point to use when loading savestates when we're tracing. void rsp_clear_registers() { memset(RSP::cpu.get_state().sr, 0, sizeof(uint32_t) * 32); memset(&RSP::cpu.get_state().cp2, 0, sizeof(RSP::cpu.get_state().cp2)); } #ifdef INTENSE_DEBUG // Need super-fast hash here. static uint64_t hash_imem(const uint8_t *data, size_t size) { uint64_t h = 0xcbf29ce484222325ull; size_t i; for (i = 0; i < size; i++) h = (h * 0x100000001b3ull) ^ data[i]; return h; } void log_rsp_mem_parallel(void) { fprintf(stderr, "IMEM HASH: 0x%016llx\n", hash_imem(RSP::rsp.IMEM, 0x1000)); fprintf(stderr, "DMEM HASH: 0x%016llx\n", hash_imem(RSP::rsp.DMEM, 0x1000)); } #endif EXPORT unsigned int CALL DoRspCycles(unsigned int first_run) { // We don't know if Mupen from the outside invalidated our IMEM. if (first_run) { RSP::cpu.get_state().last_instruction_type = RSP::VU_INSTRUCTION; RSP::cpu.get_state().instruction_pipeline = 0; RSP::cpu.invalidate_imem(); } // Run CPU until we either break or we need to fire an IRQ. RSP::cpu.get_state().pc = *RSP::rsp.SP_PC_REG & 0xfff; RSP::cpu.get_state().instruction_count = 0; #ifdef INTENSE_DEBUG fprintf(stderr, "RUN TASK: %u\n", RSP::cpu.get_state().pc); log_rsp_mem_parallel(); #endif while (!(*RSP::rsp.SP_STATUS_REG & SP_STATUS_HALT)) { auto mode = RSP::cpu.run(); if (mode == RSP::MODE_CHECK_FLAGS && (*RSP::cpu.get_state().cp0.irq & 1)) break; if (mode == RSP::MODE_EXIT) break; } *RSP::rsp.SP_PC_REG = (RSP::cpu.get_state().pc & 0xffc); return RSP::cpu.get_state().instruction_count * 1.5; // Converting RCP clock rate to CPU clock rate } EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities) { /* set version info */ if (PluginType != NULL) *PluginType = M64PLUGIN_RSP; if (PluginVersion != NULL) *PluginVersion = RSP_PARALLEL_VERSION; if (APIVersion != NULL) *APIVersion = RSP_PLUGIN_API_VERSION; if (PluginNamePtr != NULL) *PluginNamePtr = "ParaLLEl RSP"; if (Capabilities != NULL) *Capabilities = 0; return M64ERR_SUCCESS; } EXPORT void CALL RomClosed(void) { *RSP::rsp.SP_PC_REG = 0x00000000; } EXPORT void CALL InitiateRSP(RSP_INFO Rsp_Info, unsigned int *CycleCount) { if (CycleCount) *CycleCount = 0; if (Rsp_Info.DMEM == Rsp_Info.IMEM) /* usually dummy RSP data for testing */ return; /* DMA is not executed just because plugin initiates. */ RSP::rsp = Rsp_Info; *RSP::rsp.SP_PC_REG = 0x04001000 & 0x00000FFF; /* task init bug on Mupen64 */ auto **cr = RSP::cpu.get_state().cp0.cr; cr[0x0] = RSP::rsp.SP_MEM_ADDR_REG; cr[0x1] = RSP::rsp.SP_DRAM_ADDR_REG; cr[0x2] = RSP::rsp.SP_RD_LEN_REG; cr[0x3] = RSP::rsp.SP_WR_LEN_REG; cr[0x4] = RSP::rsp.SP_STATUS_REG; cr[0x5] = RSP::rsp.SP_DMA_FULL_REG; cr[0x6] = RSP::rsp.SP_DMA_BUSY_REG; cr[0x7] = RSP::rsp.SP_SEMAPHORE_REG; cr[0x8] = RSP::rsp.DPC_START_REG; cr[0x9] = RSP::rsp.DPC_END_REG; cr[0xA] = RSP::rsp.DPC_CURRENT_REG; cr[0xB] = RSP::rsp.DPC_STATUS_REG; cr[0xC] = RSP::rsp.DPC_CLOCK_REG; cr[0xD] = RSP::rsp.DPC_BUFBUSY_REG; cr[0xE] = RSP::rsp.DPC_PIPEBUSY_REG; cr[0xF] = RSP::rsp.DPC_TMEM_REG; *cr[RSP::CP0_REGISTER_SP_STATUS] = SP_STATUS_HALT; RSP::cpu.get_state().cp0.irq = RSP::rsp.MI_INTR_REG; RSP::cpu.set_dmem(reinterpret_cast(Rsp_Info.DMEM)); RSP::cpu.set_imem(reinterpret_cast(Rsp_Info.IMEM)); RSP::cpu.set_rdram(reinterpret_cast(Rsp_Info.RDRAM)); } EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context, void (*DebugCallback)(void *, int, const char *)) { /* first thing is to set the callback function for debug info */ l_DebugCallback = DebugCallback; l_DebugCallContext = Context; return M64ERR_SUCCESS; } EXPORT m64p_error CALL PluginShutdown(void) { return M64ERR_SUCCESS; } EXPORT int CALL RomOpen(void) { return 1; } }