diff --git a/parallel.cpp b/parallel.cpp index c7ce7a0..e480102 100644 --- a/parallel.cpp +++ b/parallel.cpp @@ -4,6 +4,7 @@ #include "rsp_jit.hpp" #endif #include +#include #include "m64p_plugin.h" #include "rsp_1.1.h" @@ -19,8 +20,6 @@ RSP::CPU cpu; #else RSP::JIT::CPU cpu; #endif -short MFC0_count[32]; -int SP_STATUS_TIMEOUT; } // namespace RSP extern "C" @@ -52,47 +51,33 @@ extern "C" EXPORT unsigned int CALL parallelRSPDoRspCycles(unsigned int cycles) { - if (*RSP::rsp.SP_STATUS_REG & SP_STATUS_HALT) - return 0; - // We don't know if Mupen from the outside invalidated our IMEM. - RSP::cpu.invalidate_imem(); + if (cycles) + { + 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 - for (auto &count : RSP::MFC0_count) - count = 0; - 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 = 0x04001000 | (RSP::cpu.get_state().pc & 0xffc); - - // From CXD4. - if (*RSP::rsp.SP_STATUS_REG & SP_STATUS_BROKE) - return cycles; - else if (*RSP::cpu.get_state().cp0.irq & 1) - RSP::rsp.CheckInterrupts(); - else if (*RSP::rsp.SP_STATUS_REG & SP_STATUS_HALT) - return cycles; - else if (*RSP::rsp.SP_SEMAPHORE_REG != 0) // Semaphore lock fixes. - { - } - else - RSP::SP_STATUS_TIMEOUT = 16; // From now on, wait 16 times, not 0x7fff - - // CPU restarts with the correct SIGs. - *RSP::rsp.SP_STATUS_REG &= ~SP_STATUS_HALT; + *RSP::rsp.SP_PC_REG = (RSP::cpu.get_state().pc & 0xffc); return cycles; } @@ -153,9 +138,6 @@ extern "C" *cr[RSP::CP0_REGISTER_SP_STATUS] = SP_STATUS_HALT; RSP::cpu.get_state().cp0.irq = RSP::rsp.MI_INTR_REG; - // From CXD4. - RSP::SP_STATUS_TIMEOUT = 0x7fff; - 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)); diff --git a/rsp/cp0.cpp b/rsp/cp0.cpp index 6647d58..3c268ec 100644 --- a/rsp/cp0.cpp +++ b/rsp/cp0.cpp @@ -6,8 +6,6 @@ namespace RSP { extern RSP_INFO rsp; -extern short MFC0_count[32]; -extern int SP_STATUS_TIMEOUT; } // namespace RSP #endif @@ -28,34 +26,15 @@ extern "C" rsp->sr[rt] = res; #ifdef PARALLEL_INTEGRATION - if (rd == CP0_REGISTER_SP_STATUS) + if (rd == CP0_REGISTER_SP_SEMAPHORE) { - // Might be waiting for the CPU to set a signal bit on the STATUS register. Increment timeout - RSP::MFC0_count[rt] += 1; - if (RSP::MFC0_count[rt] >= RSP::SP_STATUS_TIMEOUT) - { - *RSP::rsp.SP_STATUS_REG |= SP_STATUS_HALT; - return MODE_CHECK_FLAGS; - } + *rsp->cp0.cr[CP0_REGISTER_SP_SEMAPHORE] = 1; + return MODE_EXIT; } -#endif - -#if 0 // FIXME: this is broken with upstream mupen64plus-core - if (rd == CP0_REGISTER_SP_SEMAPHORE) + // We don't return control to the CPU if the RDP FREEZE bit is set, doing so seems to cause flickering + else if (rd == CP0_REGISTER_SP_STATUS && (*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] & DPC_STATUS_FREEZE) == 0) { - if (*rsp->cp0.cr[CP0_REGISTER_SP_SEMAPHORE]) - { -#ifdef PARALLEL_INTEGRATION - RSP::MFC0_count[rt] += 8; // Almost certainly waiting on the CPU. Timeout faster. - if (RSP::MFC0_count[rt] >= RSP::SP_STATUS_TIMEOUT) - { - *RSP::rsp.SP_STATUS_REG |= SP_STATUS_HALT; - return MODE_CHECK_FLAGS; - } -#endif - } - else - *rsp->cp0.cr[CP0_REGISTER_SP_SEMAPHORE] = 1; + return MODE_EXIT; } #endif @@ -65,12 +44,44 @@ extern "C" return MODE_CONTINUE; } -#define RSP_HANDLE_STATUS_WRITE(flag) \ - switch (rt & (SP_SET_##flag | SP_CLR_##flag)) \ - { \ - case SP_SET_##flag: status |= SP_STATUS_##flag; break; \ - case SP_CLR_##flag: status &= ~SP_STATUS_##flag; break; \ - default: break; \ + static inline void rdp_status_write(RSP::CPUState *rsp, uint32_t rt) + { + uint32_t status = *rsp->cp0.cr[CP0_REGISTER_CMD_STATUS]; + if (rt & DPC_CLR_XBUS_DMEM_DMA) + status &= ~DPC_STATUS_XBUS_DMEM_DMA; + else if (rt & DPC_SET_XBUS_DMEM_DMA) + status |= DPC_STATUS_XBUS_DMEM_DMA; + + if (rt & DPC_CLR_FREEZE) + status &= ~DPC_STATUS_FREEZE; + else if (rt & DPC_SET_FREEZE) + status |= DPC_STATUS_FREEZE; + + if (rt & DPC_CLR_FLUSH) + status &= ~DPC_STATUS_FLUSH; + else if (rt & DPC_SET_FLUSH) + status |= DPC_STATUS_FLUSH; + + if (rt & DPC_CLR_TMEM_CTR) + { + status &= ~DPC_STATUS_TMEM_BUSY; + *rsp->cp0.cr[CP0_REGISTER_CMD_TMEM_BUSY] = 0; + } + if (rt & DPC_CLR_PIPE_CTR) + { + status &= ~DPC_STATUS_PIPE_BUSY; + *rsp->cp0.cr[CP0_REGISTER_CMD_PIPE_BUSY] = 0; + } + if (rt & DPC_CLR_CMD_CTR) + { + status &= ~DPC_STATUS_CMD_BUSY; + *rsp->cp0.cr[CP0_REGISTER_CMD_BUSY] = 0; + } + + if (rt & DPC_CLR_CLOCK_CTR) + *rsp->cp0.cr[CP0_REGISTER_CMD_CLOCK] = 0; + + *rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] = status; } static inline int rsp_status_write(RSP::CPUState *rsp, uint32_t rt) @@ -79,28 +90,69 @@ extern "C" uint32_t status = *rsp->cp0.cr[CP0_REGISTER_SP_STATUS]; - RSP_HANDLE_STATUS_WRITE(HALT) - RSP_HANDLE_STATUS_WRITE(SSTEP) - RSP_HANDLE_STATUS_WRITE(INTR_BREAK) - RSP_HANDLE_STATUS_WRITE(SIG0) - RSP_HANDLE_STATUS_WRITE(SIG1) - RSP_HANDLE_STATUS_WRITE(SIG2) - RSP_HANDLE_STATUS_WRITE(SIG3) - RSP_HANDLE_STATUS_WRITE(SIG4) - RSP_HANDLE_STATUS_WRITE(SIG5) - RSP_HANDLE_STATUS_WRITE(SIG6) - RSP_HANDLE_STATUS_WRITE(SIG7) - - switch (rt & (SP_SET_INTR | SP_CLR_INTR)) - { - case SP_SET_INTR: *rsp->cp0.irq |= 1; break; - case SP_CLR_INTR: *rsp->cp0.irq &= ~1; break; - default: break; - } + if ((rt & SP_CLR_HALT) && !(rt & SP_SET_HALT)) + status &= ~SP_STATUS_HALT; + if ((rt & SP_SET_HALT) && !(rt & SP_CLR_HALT)) + status |= SP_STATUS_HALT; if (rt & SP_CLR_BROKE) status &= ~SP_STATUS_BROKE; + if ((rt & SP_CLR_INTR) && !(rt & SP_SET_INTR)) + *rsp->cp0.irq &= ~1; + if ((rt & SP_SET_INTR) && !(rt & SP_CLR_INTR)) + *rsp->cp0.irq |= 1; + + if ((rt & SP_CLR_SSTEP) && !(rt & SP_SET_SSTEP)) + status &= ~SP_STATUS_SSTEP; + if ((rt & SP_SET_SSTEP) && !(rt & SP_CLR_SSTEP)) + status |= SP_STATUS_SSTEP; + + if ((rt & SP_CLR_INTR_BREAK) && !(rt & SP_SET_INTR_BREAK)) + status &= ~SP_STATUS_INTR_BREAK; + if ((rt & SP_SET_INTR_BREAK) && !(rt & SP_CLR_INTR_BREAK)) + status |= SP_STATUS_INTR_BREAK; + + if ((rt & SP_CLR_SIG0) && !(rt & SP_SET_SIG0)) + status &= ~SP_STATUS_SIG0; + if ((rt & SP_SET_SIG0) && !(rt & SP_CLR_SIG0)) + status |= SP_STATUS_SIG0; + + if ((rt & SP_CLR_SIG1) && !(rt & SP_SET_SIG1)) + status &= ~SP_STATUS_SIG1; + if ((rt & SP_SET_SIG1) && !(rt & SP_CLR_SIG1)) + status |= SP_STATUS_SIG1; + + if ((rt & SP_CLR_SIG2) && !(rt & SP_SET_SIG2)) + status &= ~SP_STATUS_SIG2; + if ((rt & SP_SET_SIG2) && !(rt & SP_CLR_SIG2)) + status |= SP_STATUS_SIG2; + + if ((rt & SP_CLR_SIG3) && !(rt & SP_SET_SIG3)) + status &= ~SP_STATUS_SIG3; + if ((rt & SP_SET_SIG3) && !(rt & SP_CLR_SIG3)) + status |= SP_STATUS_SIG3; + + if ((rt & SP_CLR_SIG4) && !(rt & SP_SET_SIG4)) + status &= ~SP_STATUS_SIG4; + if ((rt & SP_SET_SIG4) && !(rt & SP_CLR_SIG4)) + status |= SP_STATUS_SIG4; + + if ((rt & SP_CLR_SIG5) && !(rt & SP_SET_SIG5)) + status &= ~SP_STATUS_SIG5; + if ((rt & SP_SET_SIG5) && !(rt & SP_CLR_SIG5)) + status |= SP_STATUS_SIG5; + + if ((rt & SP_CLR_SIG6) && !(rt & SP_SET_SIG6)) + status &= ~SP_STATUS_SIG6; + if ((rt & SP_SET_SIG6) && !(rt & SP_CLR_SIG6)) + status |= SP_STATUS_SIG6; + + if ((rt & SP_CLR_SIG7) && !(rt & SP_SET_SIG7)) + status &= ~SP_STATUS_SIG7; + if ((rt & SP_SET_SIG7) && !(rt & SP_CLR_SIG7)) + status |= SP_STATUS_SIG7; + *rsp->cp0.cr[CP0_REGISTER_SP_STATUS] = status; return ((*rsp->cp0.irq & 1) || (status & SP_STATUS_HALT)) ? MODE_CHECK_FLAGS : MODE_CONTINUE; } @@ -109,14 +161,9 @@ extern "C" static int rsp_dma_read(RSP::CPUState *rsp) { uint32_t length_reg = *rsp->cp0.cr[CP0_REGISTER_DMA_READ_LENGTH]; - uint32_t length = (length_reg & 0xFFF) + 1; - uint32_t skip = (length_reg >> 20) & 0xFFF; - unsigned count = (length_reg >> 12) & 0xFF; - - // Force alignment. - length = (length + 0x7) & ~0x7; - *rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] &= ~0x3; - *rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] &= ~0x7; + uint32_t length = ((length_reg & 0xFFF) | 7) + 1; + uint32_t skip = (length_reg >> 20) & 0xFF8; + unsigned count = ((length_reg >> 12) & 0xFF) + 1; // Check length. if (((*rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] & 0xFFF) + length) > 0x1000) @@ -156,7 +203,7 @@ extern "C" source += length + skip; dest += length; - } while (++i <= count); + } while (++i < count); *rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] = source; *rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] = dest; @@ -171,14 +218,9 @@ extern "C" static void rsp_dma_write(RSP::CPUState *rsp) { uint32_t length_reg = *rsp->cp0.cr[CP0_REGISTER_DMA_WRITE_LENGTH]; - uint32_t length = (length_reg & 0xFFF) + 1; - uint32_t skip = (length_reg >> 20) & 0xFFF; - unsigned count = (length_reg >> 12) & 0xFF; - - // Force alignment. - length = (length + 0x7) & ~0x7; - *rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] &= ~0x3; - *rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] &= ~0x7; + uint32_t length = ((length_reg & 0xFFF) | 7) + 1; + uint32_t skip = (length_reg >> 20) & 0xFF8; + unsigned count = ((length_reg >> 12) & 0xFF) + 1; // Check length. if (((*rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] & 0xFFF) + length) > 0x1000) @@ -210,7 +252,7 @@ extern "C" source += length; dest += length + skip; - } while (++i <= count); + } while (++i < count); *rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] = source; *rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] = dest; @@ -228,11 +270,11 @@ extern "C" switch (static_cast(rd & 15)) { case CP0_REGISTER_DMA_CACHE: - *rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] = val & 0x1fff; + *rsp->cp0.cr[CP0_REGISTER_DMA_CACHE] = val & 0x1ff8; break; case CP0_REGISTER_DMA_DRAM: - *rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] = val & 0xffffff; + *rsp->cp0.cr[CP0_REGISTER_DMA_DRAM] = val & 0xfffff8; break; case CP0_REGISTER_DMA_READ_LENGTH: @@ -254,26 +296,34 @@ extern "C" return rsp_status_write(rsp, val); case CP0_REGISTER_SP_SEMAPHORE: - // Any write to the semaphore register, regardless of value, sets it to 0 for the next read *rsp->cp0.cr[CP0_REGISTER_SP_SEMAPHORE] = 0; break; case CP0_REGISTER_CMD_START: #ifdef INTENSE_DEBUG - fprintf(stderr, "CMD_START 0x%x\n", val & 0xfffffff8u); + fprintf(stderr, "CMD_START 0x%x\n", val & 0xfffff8u); #endif - *rsp->cp0.cr[CP0_REGISTER_CMD_START] = *rsp->cp0.cr[CP0_REGISTER_CMD_CURRENT] = - *rsp->cp0.cr[CP0_REGISTER_CMD_END] = val & 0xfffffff8u; + if (!(*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] & DPC_STATUS_START_VALID)) + { + *rsp->cp0.cr[CP0_REGISTER_CMD_START] = val & 0xfffff8u; + } + *rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] |= DPC_STATUS_START_VALID; break; case CP0_REGISTER_CMD_END: #ifdef INTENSE_DEBUG - fprintf(stderr, "CMD_END 0x%x\n", val & 0xfffffff8u); + fprintf(stderr, "CMD_END 0x%x\n", val & 0xfffff8u); #endif - *rsp->cp0.cr[CP0_REGISTER_CMD_END] = val & 0xfffffff8u; - + *rsp->cp0.cr[CP0_REGISTER_CMD_END] = val & 0xfffff8u; + if (*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] & DPC_STATUS_START_VALID) + { + *rsp->cp0.cr[CP0_REGISTER_CMD_CURRENT] = *rsp->cp0.cr[CP0_REGISTER_CMD_START]; + *rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] &= ~DPC_STATUS_START_VALID; + } #ifdef PARALLEL_INTEGRATION RSP::rsp.ProcessRdpList(); + if (*rsp->cp0.irq & 0x20) + return MODE_EXIT; #endif break; @@ -282,14 +332,7 @@ extern "C" break; case CP0_REGISTER_CMD_STATUS: - *rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] &= ~(!!(val & 0x1) << 0); - *rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] |= (!!(val & 0x2) << 0); - *rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] &= ~(!!(val & 0x4) << 1); - *rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] |= (!!(val & 0x8) << 1); - *rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] &= ~(!!(val & 0x10) << 2); - *rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] |= (!!(val & 0x20) << 2); - *rsp->cp0.cr[CP0_REGISTER_CMD_TMEM_BUSY] &= !(val & 0x40) * -1; - *rsp->cp0.cr[CP0_REGISTER_CMD_CLOCK] &= !(val & 0x200) * -1; + rdp_status_write(rsp, val); break; case CP0_REGISTER_CMD_CURRENT: diff --git a/rsp/ls.cpp b/rsp/ls.cpp index 0544dc3..b03f8a2 100644 --- a/rsp/ls.cpp +++ b/rsp/ls.cpp @@ -148,7 +148,7 @@ extern "C" auto *reg = rsp->cp2.regs[rt].e; for (unsigned i = 0; i < 8; i++) - reg[i] = READ_MEM_U8(rsp->dmem, (addr + (i + index & 0xf)) & 0xfff) << 8; + reg[i] = READ_MEM_U8(rsp->dmem, (addr + ((i + index) & 0xf)) & 0xfff) << 8; } void RSP_SPV(RSP::CPUState *rsp, unsigned rt, unsigned e, int offset, unsigned base) @@ -175,7 +175,7 @@ extern "C" auto *reg = rsp->cp2.regs[rt].e; for (unsigned i = 0; i < 8; i++) - reg[i] = READ_MEM_U8(rsp->dmem, (addr + (i + index & 0xf)) & 0xfff) << 7; + reg[i] = READ_MEM_U8(rsp->dmem, (addr + ((i + index) & 0xf)) & 0xfff) << 7; } void RSP_SUV(RSP::CPUState *rsp, unsigned rt, unsigned e, int offset, unsigned base) @@ -201,7 +201,7 @@ extern "C" auto *reg = rsp->cp2.regs[rt].e; for (unsigned i = 0; i < 8; i++) - reg[i] = (uint16_t)READ_MEM_U8(rsp->dmem, (addr + (index + i * 2 & 0xf)) & 0xfff) << 7; + reg[i] = (uint16_t)READ_MEM_U8(rsp->dmem, (addr + ((index + i * 2) & 0xf)) & 0xfff) << 7; } void RSP_SHV(RSP::CPUState *rsp, unsigned rt, unsigned e, int offset, unsigned base) @@ -215,8 +215,8 @@ extern "C" for (unsigned i = 0; i < 8; i++) { const unsigned b = e + (i << 1); - const uint8_t byte = byteFromHalfWords(reg, b & 0xf) << 1 | byteFromHalfWords(reg, b + 1 & 0xf) >> 7; - WRITE_MEM_U8(rsp->dmem, addr + (index + i * 2 & 0xf), byte); + const uint8_t byte = byteFromHalfWords(reg, b & 0xf) << 1 | byteFromHalfWords(reg, (b + 1) & 0xf) >> 7; + WRITE_MEM_U8(rsp->dmem, addr + ((index + i * 2) & 0xf), byte); } } @@ -232,8 +232,8 @@ extern "C" for (unsigned i = 0; i < 4; i++) { - temp[i] = (uint16_t)READ_MEM_U8(rsp->dmem, (addr + (index + i * 4 & 0xf)) & 0xfff) << 7; - temp[i+4] = (uint16_t)READ_MEM_U8(rsp->dmem, (addr + (index + i * 4 + 8 & 0xf)) & 0xfff) << 7; + temp[i] = (uint16_t)READ_MEM_U8(rsp->dmem, (addr + ((index + i * 4) & 0xf)) & 0xfff) << 7; + temp[i+4] = (uint16_t)READ_MEM_U8(rsp->dmem, (addr + ((index + i * 4 + 8) & 0xf)) & 0xfff) << 7; } for (unsigned i = e; i < end; i++) @@ -243,8 +243,8 @@ extern "C" #define RSP_SFV_CASE(a,b,c,d) \ WRITE_MEM_U8(rsp->dmem, addr + base, int16_t(reg[a]) >> 7); \ WRITE_MEM_U8(rsp->dmem, addr + 4 + base, int16_t(reg[b]) >> 7); \ - WRITE_MEM_U8(rsp->dmem, addr + (8 + base & 0xf), int16_t(reg[c]) >> 7); \ - WRITE_MEM_U8(rsp->dmem, addr + (12 + base & 0xf), int16_t(reg[d]) >> 7); + WRITE_MEM_U8(rsp->dmem, addr + ((8 + base) & 0xf), int16_t(reg[c]) >> 7); \ + WRITE_MEM_U8(rsp->dmem, addr + ((12 + base) & 0xf), int16_t(reg[d]) >> 7); void RSP_SFV(RSP::CPUState *rsp, unsigned rt, unsigned e, int offset, unsigned base) { @@ -281,8 +281,8 @@ extern "C" default: WRITE_MEM_U8(rsp->dmem, addr + base, 0); WRITE_MEM_U8(rsp->dmem, addr + 4 + base, 0); - WRITE_MEM_U8(rsp->dmem, addr + (8 + base & 0xf), 0); - WRITE_MEM_U8(rsp->dmem, addr + (12 + base & 0xf), 0); + WRITE_MEM_U8(rsp->dmem, addr + ((8 + base) & 0xf), 0); + WRITE_MEM_U8(rsp->dmem, addr + ((12 + base) & 0xf), 0); break; } } @@ -351,7 +351,7 @@ extern "C" addr &= ~0xf; for (unsigned i = e; i < end; i++) - WRITE_MEM_U8(rsp->dmem, addr++, byteFromHalfWords(rsp->cp2.regs[rt].e, i + base & 0xf)); + WRITE_MEM_U8(rsp->dmem, addr++, byteFromHalfWords(rsp->cp2.regs[rt].e, (i + base) & 0xf)); } void RSP_LTV(RSP::CPUState *rsp, unsigned rt, unsigned e, int offset, unsigned base) diff --git a/rsp_jit.cpp b/rsp_jit.cpp index 2052404..e9fcd92 100644 --- a/rsp_jit.cpp +++ b/rsp_jit.cpp @@ -1927,14 +1927,13 @@ ReturnMode CPU::run() { case MODE_BREAK: *state.cp0.cr[CP0_REGISTER_SP_STATUS] |= SP_STATUS_BROKE | SP_STATUS_HALT; - if (*state.cp0.cr[CP0_REGISTER_SP_STATUS] & SP_STATUS_INTR_BREAK) - *state.cp0.irq |= 1; #ifndef PARALLEL_INTEGRATION print_registers(); #endif return MODE_BREAK; case MODE_CHECK_FLAGS: + case MODE_EXIT: case MODE_DMA_READ: return static_cast(ret); diff --git a/state.hpp b/state.hpp index 3822c73..f8c2135 100644 --- a/state.hpp +++ b/state.hpp @@ -48,6 +48,31 @@ enum CP0Registers CP0_REGISTER_CMD_TMEM_BUSY = 15, }; +// CMD_STATUS read bits. +#define DPC_STATUS_XBUS_DMEM_DMA 0x001 +#define DPC_STATUS_FREEZE 0x002 +#define DPC_STATUS_FLUSH 0x004 +#define DPC_STATUS_START_GCLK 0x008 +#define DPC_STATUS_TMEM_BUSY 0x010 +#define DPC_STATUS_PIPE_BUSY 0x020 +#define DPC_STATUS_CMD_BUSY 0x040 +#define DPC_STATUS_CBUF_READY 0x080 +#define DPC_STATUS_DMA_BUSY 0x100 +#define DPC_STATUS_END_VALID 0x200 +#define DPC_STATUS_START_VALID 0x400 + +// CMD_STATUS write bits. +#define DPC_CLR_XBUS_DMEM_DMA 0x001 +#define DPC_SET_XBUS_DMEM_DMA 0x002 +#define DPC_CLR_FREEZE 0x004 +#define DPC_SET_FREEZE 0x008 +#define DPC_CLR_FLUSH 0x010 +#define DPC_SET_FLUSH 0x020 +#define DPC_CLR_TMEM_CTR 0x040 +#define DPC_CLR_PIPE_CTR 0x080 +#define DPC_CLR_CMD_CTR 0x100 +#define DPC_CLR_CLOCK_CTR 0x200 + // SP_STATUS read bits. #define SP_STATUS_HALT 0x0001 #define SP_STATUS_BROKE 0x0002 @@ -117,6 +142,9 @@ struct alignas(64) CP2 struct CPUState { uint32_t pc = 0; + uint32_t instruction_count = 0; + uint32_t last_instruction_type = 0; + uint32_t instruction_pipeline = 0; uint32_t dirty_blocks = 0; static_assert(CODE_BLOCKS <= 32, "Code blocks must fit in 32-bit register."); @@ -138,7 +166,14 @@ enum ReturnMode MODE_CONTINUE = 1, MODE_BREAK = 2, MODE_DMA_READ = 3, - MODE_CHECK_FLAGS = 4 + MODE_CHECK_FLAGS = 4, + MODE_EXIT = 5 +}; + +enum InstructionType +{ + VU_INSTRUCTION = 0, + SU_INSTRUCTION = 1 }; } // namespace RSP