diff --git a/parallel-rsp/parallel.cpp b/parallel-rsp/parallel.cpp index 0f43ada..e46c564 100644 --- a/parallel-rsp/parallel.cpp +++ b/parallel-rsp/parallel.cpp @@ -98,6 +98,8 @@ extern "C" 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); @@ -107,12 +109,6 @@ extern "C" return RSP::cpu.get_state().instruction_count * 1.5; // Converting RCP clock rate to CPU clock rate else if (*RSP::cpu.get_state().cp0.irq & 1) RSP::rsp.CheckInterrupts(); - else if (*RSP::rsp.SP_SEMAPHORE_REG != 0) // Semaphore lock fixes. - { - } - - // CPU restarts with the correct SIGs. - *RSP::rsp.SP_STATUS_REG &= ~SP_STATUS_HALT; return RSP::cpu.get_state().instruction_count * 1.5; // Converting RCP clock rate to CPU clock rate } diff --git a/parallel-rsp/rsp/cp0.cpp b/parallel-rsp/rsp/cp0.cpp index c5abb31..2c77ef0 100644 --- a/parallel-rsp/rsp/cp0.cpp +++ b/parallel-rsp/rsp/cp0.cpp @@ -27,23 +27,22 @@ extern "C" if (rt) rsp->sr[rt] = res; - // CFG_MEND_SEMAPHORE_LOCK == 0 by default, - // so don't bother implementing semaphores. - // It makes Mario Golf run terribly for some reason. - #ifdef PARALLEL_INTEGRATION // WAIT_FOR_CPU_HOST. From CXD4. if (rd == CP0_REGISTER_SP_STATUS) { --rsp->instruction_count; // Some games check the STATUS reg more than normal since we don't really yield properly RSP::MFC0_count[rt] += 1; - //We don't return control to the CPU if the RDP FREEZE bit is set, doing so seems to cause flickering - if (RSP::MFC0_count[rt] >= RSP::SP_STATUS_TIMEOUT && (*rsp->cp0.cr[CP0_REGISTER_CMD_STATUS] & 0x2) == 0) - { - *RSP::rsp.SP_STATUS_REG |= SP_STATUS_HALT; - return MODE_CHECK_FLAGS; - } + } + else if (rd == CP0_REGISTER_SP_RESERVED) + { + rsp->instruction_count += 2; // Needed for DK64 + RSP::MFC0_count[rt] += 1; + *rsp->cp0.cr[CP0_REGISTER_SP_RESERVED] = 1; + } + if (RSP::MFC0_count[rt] >= RSP::SP_STATUS_TIMEOUT) + return MODE_EXIT; #endif //if (rd == 4) // SP_STATUS_REG @@ -98,67 +97,67 @@ extern "C" uint32_t status = *rsp->cp0.cr[CP0_REGISTER_SP_STATUS]; - if (rt & SP_CLR_HALT) + if ((rt & SP_CLR_HALT) && !(rt & SP_SET_HALT)) status &= ~SP_STATUS_HALT; - else if (rt & SP_SET_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) + if ((rt & SP_CLR_INTR) && !(rt & SP_SET_INTR)) *rsp->cp0.irq &= ~1; - else if (rt & SP_SET_INTR) + if ((rt & SP_SET_INTR) && !(rt & SP_CLR_INTR)) *rsp->cp0.irq |= 1; - if (rt & SP_CLR_SSTEP) + if ((rt & SP_CLR_SSTEP) && !(rt & SP_SET_SSTEP)) status &= ~SP_STATUS_SSTEP; - else if (rt & SP_SET_SSTEP) + if ((rt & SP_SET_SSTEP) && !(rt & SP_CLR_SSTEP)) status |= SP_STATUS_SSTEP; - if (rt & SP_CLR_INTR_BREAK) + if ((rt & SP_CLR_INTR_BREAK) && !(rt & SP_SET_INTR_BREAK)) status &= ~SP_STATUS_INTR_BREAK; - else if (rt & SP_SET_INTR_BREAK) + if ((rt & SP_SET_INTR_BREAK) && !(rt & SP_CLR_INTR_BREAK)) status |= SP_STATUS_INTR_BREAK; - if (rt & SP_CLR_SIG0) + if ((rt & SP_CLR_SIG0) && !(rt & SP_SET_SIG0)) status &= ~SP_STATUS_SIG0; - else if (rt & SP_SET_SIG0) + if ((rt & SP_SET_SIG0) && !(rt & SP_CLR_SIG0)) status |= SP_STATUS_SIG0; - if (rt & SP_CLR_SIG1) + if ((rt & SP_CLR_SIG1) && !(rt & SP_SET_SIG1)) status &= ~SP_STATUS_SIG1; - else if (rt & SP_SET_SIG1) + if ((rt & SP_SET_SIG1) && !(rt & SP_CLR_SIG1)) status |= SP_STATUS_SIG1; - if (rt & SP_CLR_SIG2) + if ((rt & SP_CLR_SIG2) && !(rt & SP_SET_SIG2)) status &= ~SP_STATUS_SIG2; - else if (rt & SP_SET_SIG2) + if ((rt & SP_SET_SIG2) && !(rt & SP_CLR_SIG2)) status |= SP_STATUS_SIG2; - if (rt & SP_CLR_SIG3) + if ((rt & SP_CLR_SIG3) && !(rt & SP_SET_SIG3)) status &= ~SP_STATUS_SIG3; - else if (rt & SP_SET_SIG3) + if ((rt & SP_SET_SIG3) && !(rt & SP_CLR_SIG3)) status |= SP_STATUS_SIG3; - if (rt & SP_CLR_SIG4) + if ((rt & SP_CLR_SIG4) && !(rt & SP_SET_SIG4)) status &= ~SP_STATUS_SIG4; - else if (rt & SP_SET_SIG4) + if ((rt & SP_SET_SIG4) && !(rt & SP_CLR_SIG4)) status |= SP_STATUS_SIG4; - if (rt & SP_CLR_SIG5) + if ((rt & SP_CLR_SIG5) && !(rt & SP_SET_SIG5)) status &= ~SP_STATUS_SIG5; - else if (rt & SP_SET_SIG5) + if ((rt & SP_SET_SIG5) && !(rt & SP_CLR_SIG5)) status |= SP_STATUS_SIG5; - if (rt & SP_CLR_SIG6) + if ((rt & SP_CLR_SIG6) && !(rt & SP_SET_SIG6)) status &= ~SP_STATUS_SIG6; - else if (rt & SP_SET_SIG6) + if ((rt & SP_SET_SIG6) && !(rt & SP_CLR_SIG6)) status |= SP_STATUS_SIG6; - if (rt & SP_CLR_SIG7) + if ((rt & SP_CLR_SIG7) && !(rt & SP_SET_SIG7)) status &= ~SP_STATUS_SIG7; - else if (rt & SP_SET_SIG7) + if ((rt & SP_SET_SIG7) && !(rt & SP_CLR_SIG7)) status |= SP_STATUS_SIG7; *rsp->cp0.cr[CP0_REGISTER_SP_STATUS] = status; @@ -169,14 +168,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) @@ -216,7 +210,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; @@ -230,14 +224,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) @@ -269,7 +258,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; @@ -286,11 +275,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: @@ -312,7 +301,6 @@ extern "C" return rsp_status_write(rsp, val); case CP0_REGISTER_SP_RESERVED: - // CXD4 forces this to 0. *rsp->cp0.cr[CP0_REGISTER_SP_RESERVED] = 0; break; diff --git a/parallel-rsp/rsp_jit.cpp b/parallel-rsp/rsp_jit.cpp index d5d05d5..dd8ab32 100644 --- a/parallel-rsp/rsp_jit.cpp +++ b/parallel-rsp/rsp_jit.cpp @@ -269,6 +269,19 @@ extern "C" (dram[off1] << 0))); } + static jit_word_t rsp_unaligned_lwu(const uint8_t *dram, jit_word_t addr) + { + auto off0 = BYTE_ENDIAN_FIXUP(addr, 0); + auto off1 = BYTE_ENDIAN_FIXUP(addr, 1); + auto off2 = BYTE_ENDIAN_FIXUP(addr, 2); + auto off3 = BYTE_ENDIAN_FIXUP(addr, 3); + + return jit_word_t((uint32_t(dram[off0]) << 24) | + (uint32_t(dram[off1]) << 16) | + (uint32_t(dram[off2]) << 8) | + (uint32_t(dram[off3]) << 0)); + } + static void rsp_unaligned_sh(uint8_t *dram, jit_word_t addr, jit_word_t data) { auto off0 = BYTE_ENDIAN_FIXUP(addr, 0); @@ -924,7 +937,7 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr, uint32_t type = instr >> 26; -#define NOP_IF_RD_ZERO() if (rd == 0) { break; } +#define NOP_IF_RD_ZERO() //if (rd == 0) { break; } #define NOP_IF_RT_ZERO() if (rt == 0) { break; } switch (type) @@ -1613,6 +1626,16 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr, break; } + case 047: // LWU + { + jit_emit_load_operation(_jit, pc, instr, + [](jit_state_t *_jit, unsigned a, unsigned b, unsigned c) { jit_ldxr_ui(a, b, c); }, + "lwu", + reinterpret_cast(rsp_unaligned_lwu), + 0, last_info); + break; + } + case 050: // SB { jit_emit_store_operation(_jit, pc, instr, @@ -1952,6 +1975,7 @@ ReturnMode CPU::run() return MODE_BREAK; case MODE_CHECK_FLAGS: + case MODE_EXIT: case MODE_DMA_READ: return static_cast(ret); diff --git a/parallel-rsp/state.hpp b/parallel-rsp/state.hpp index dba036e..90de304 100644 --- a/parallel-rsp/state.hpp +++ b/parallel-rsp/state.hpp @@ -165,7 +165,8 @@ 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