diff --git a/src/core/bus.cpp b/src/core/bus.cpp index 5295ef7b9..63deef8a9 100644 --- a/src/core/bus.cpp +++ b/src/core/bus.cpp @@ -225,7 +225,8 @@ std::tuple Bus::CalculateMemoryTiming(MEMDELAY const TickCount byte_access_time = first; const TickCount halfword_access_time = mem_delay.data_bus_16bit ? first : (first + seq); const TickCount word_access_time = mem_delay.data_bus_16bit ? (first + seq) : (first + seq + seq + seq); - return std::tie(byte_access_time, halfword_access_time, word_access_time); + return std::tie(std::max(byte_access_time - 1, 0), std::max(halfword_access_time - 1, 0), + std::max(word_access_time - 1, 0)); } void Bus::RecalculateMemoryTimings() @@ -238,14 +239,14 @@ void Bus::RecalculateMemoryTimings() CalculateMemoryTiming(m_MEMCTRL.spu_delay_size, m_MEMCTRL.common_delay); Log_TracePrintf("BIOS Memory Timing: %u bit bus, byte=%d, halfword=%d, word=%d", - m_MEMCTRL.bios_delay_size.data_bus_16bit ? 16 : 8, m_bios_access_time[0], m_bios_access_time[1], - m_bios_access_time[2]); + m_MEMCTRL.bios_delay_size.data_bus_16bit ? 16 : 8, m_bios_access_time[0] + 1, + m_bios_access_time[1] + 1, m_bios_access_time[2] + 1); Log_TracePrintf("CDROM Memory Timing: %u bit bus, byte=%d, halfword=%d, word=%d", - m_MEMCTRL.cdrom_delay_size.data_bus_16bit ? 16 : 8, m_cdrom_access_time[0], m_cdrom_access_time[1], - m_cdrom_access_time[2]); + m_MEMCTRL.cdrom_delay_size.data_bus_16bit ? 16 : 8, m_cdrom_access_time[0] + 1, + m_cdrom_access_time[1] + 1, m_cdrom_access_time[2] + 1); Log_TracePrintf("SPU Memory Timing: %u bit bus, byte=%d, halfword=%d, word=%d", - m_MEMCTRL.spu_delay_size.data_bus_16bit ? 16 : 8, m_spu_access_time[0], m_spu_access_time[1], - m_spu_access_time[2]); + m_MEMCTRL.spu_delay_size.data_bus_16bit ? 16 : 8, m_spu_access_time[0] + 1, m_spu_access_time[1] + 1, + m_spu_access_time[2] + 1); } TickCount Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress address, u32& value) diff --git a/src/core/bus.h b/src/core/bus.h index 880559d40..021520b0f 100644 --- a/src/core/bus.h +++ b/src/core/bus.h @@ -134,10 +134,16 @@ private: enum : u32 { - RAM_ACCESS_DELAY = 6, // Nocash docs say RAM takes 6 cycles to access. MEMCTRL_REG_COUNT = 9 }; + enum : TickCount + { + RAM_READ_ACCESS_DELAY = 5, // Nocash docs say RAM takes 6 cycles to access. Subtract one because we already add a + // tick for the instruction. + RAM_WRITE_ACCESS_DELAY = 0, // Writes are free unless we're executing more than 4 stores in a row. + }; + union MEMDELAY { u32 bits; diff --git a/src/core/bus.inl b/src/core/bus.inl index 6b6ee0e58..f8e1e6a06 100644 --- a/src/core/bus.inl +++ b/src/core/bus.inl @@ -45,7 +45,7 @@ TickCount Bus::DoRAMAccess(u32 offset, u32& value) } // Nocash docs say RAM takes 6 cycles to access. - return RAM_ACCESS_DELAY; + return (type == MemoryAccessType::Read) ? RAM_READ_ACCESS_DELAY : RAM_WRITE_ACCESS_DELAY; } template @@ -92,11 +92,15 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) else if (address < (EXP1_BASE + EXP1_SIZE)) { if constexpr (type == MemoryAccessType::Read) + { value = DoReadEXP1(size, address & EXP1_MASK); + return m_exp1_access_time[static_cast(size)]; + } else + { DoWriteEXP1(size, address & EXP1_MASK, value); - - return m_exp1_access_time[static_cast(size)]; + return 0; + } } else if (address < MEMCTRL_BASE) { @@ -109,7 +113,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) else DoWriteMemoryControl(size, address & PAD_MASK, value); - return 1; + return 0; } else if (address < (PAD_BASE + PAD_SIZE)) { @@ -118,7 +122,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) else DoWritePad(size, address & PAD_MASK, value); - return 1; + return 0; } else if (address < (SIO_BASE + SIO_SIZE)) { @@ -127,7 +131,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) else DoWriteSIO(size, address & SIO_MASK, value); - return 1; + return 0; } else if (address < (MEMCTRL2_BASE + MEMCTRL2_SIZE)) { @@ -136,7 +140,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) else DoWriteMemoryControl2(size, address & PAD_MASK, value); - return 1; + return 0; } else if (address < (INTERRUPT_CONTROLLER_BASE + INTERRUPT_CONTROLLER_SIZE)) { @@ -145,7 +149,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) else DoWriteInterruptController(size, address & INTERRUPT_CONTROLLER_MASK, value); - return 1; + return 0; } else if (address < (DMA_BASE + DMA_SIZE)) { @@ -154,7 +158,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) else DoWriteDMA(size, address & DMA_MASK, value); - return 1; + return 0; } else if (address < (TIMERS_BASE + TIMERS_SIZE)) { @@ -163,7 +167,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) else DoWriteTimers(size, address & TIMERS_MASK, value); - return 1; + return 0; } else if (address < CDROM_BASE) { @@ -172,11 +176,15 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) else if (address < (CDROM_BASE + GPU_SIZE)) { if constexpr (type == MemoryAccessType::Read) + { value = DoReadCDROM(size, address & CDROM_MASK); + return m_cdrom_access_time[static_cast(size)]; + } else + { DoWriteCDROM(size, address & CDROM_MASK, value); - - return m_cdrom_access_time[static_cast(size)]; + return 0; + } } else if (address < (GPU_BASE + GPU_SIZE)) { @@ -185,7 +193,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) else DoWriteGPU(size, address & GPU_MASK, value); - return 1; + return 0; } else if (address < (MDEC_BASE + MDEC_SIZE)) { @@ -194,7 +202,7 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) else DoWriteMDEC(size, address & MDEC_MASK, value); - return 1; + return 0; } else if (address < SPU_BASE) { @@ -203,11 +211,15 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) else if (address < (SPU_BASE + SPU_SIZE)) { if constexpr (type == MemoryAccessType::Read) + { value = DoReadSPU(size, address & SPU_MASK); + return m_spu_access_time[static_cast(size)]; + } else + { DoWriteSPU(size, address & SPU_MASK, value); - - return m_spu_access_time[static_cast(size)]; + return 0; + } } else if (address < EXP2_BASE) { @@ -216,11 +228,15 @@ TickCount Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) else if (address < (EXP2_BASE + EXP2_SIZE)) { if constexpr (type == MemoryAccessType::Read) + { value = DoReadEXP2(size, address & EXP2_MASK); + return m_exp2_access_time[static_cast(size)]; + } else + { DoWriteEXP2(size, address & EXP2_MASK, value); - - return m_exp2_access_time[static_cast(size)]; + return 0; + } } else if (address < BIOS_BASE) { diff --git a/src/core/cpu_core.cpp b/src/core/cpu_core.cpp index a79f2e24b..705260c43 100644 --- a/src/core/cpu_core.cpp +++ b/src/core/cpu_core.cpp @@ -123,7 +123,7 @@ bool Core::ReadMemoryByte(VirtualMemoryAddress addr, u8* value) return false; } - AddTicks(cycles - 1); + AddTicks(cycles); return true; } @@ -141,7 +141,7 @@ bool Core::ReadMemoryHalfWord(VirtualMemoryAddress addr, u16* value) return false; } - AddTicks(cycles - 1); + AddTicks(cycles); return true; } @@ -157,7 +157,7 @@ bool Core::ReadMemoryWord(VirtualMemoryAddress addr, u32* value) return false; } - AddTicks(cycles - 1); + AddTicks(cycles); return true; } @@ -171,7 +171,7 @@ bool Core::WriteMemoryByte(VirtualMemoryAddress addr, u8 value) return false; } - AddTicks(cycles - 1); + DebugAssert(cycles == 0); return true; } @@ -188,8 +188,8 @@ bool Core::WriteMemoryHalfWord(VirtualMemoryAddress addr, u16 value) return false; } - AddTicks(cycles - 1); - return cycles; + DebugAssert(cycles == 0); + return true; } bool Core::WriteMemoryWord(VirtualMemoryAddress addr, u32 value) @@ -204,7 +204,7 @@ bool Core::WriteMemoryWord(VirtualMemoryAddress addr, u32 value) return false; } - AddTicks(cycles - 1); + DebugAssert(cycles == 0); return true; } diff --git a/src/core/cpu_core.inl b/src/core/cpu_core.inl index 1e68ed650..c21155afb 100644 --- a/src/core/cpu_core.inl +++ b/src/core/cpu_core.inl @@ -15,14 +15,14 @@ TickCount Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value) if constexpr (type == MemoryAccessType::Write) { if (m_cop0_regs.sr.Isc) - return 1; + return 0; } const PhysicalMemoryAddress phys_addr = address & UINT32_C(0x1FFFFFFF); if ((phys_addr & DCACHE_LOCATION_MASK) == DCACHE_LOCATION) { DoScratchpadAccess(phys_addr, value); - return 1; + return 0; } return m_bus->DispatchAccess(phys_addr, value); @@ -41,14 +41,14 @@ TickCount Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value) if constexpr (type == MemoryAccessType::Write) { if (m_cop0_regs.sr.Isc) - return 1; + return 0; } const PhysicalMemoryAddress phys_addr = address & UINT32_C(0x1FFFFFFF); if ((phys_addr & DCACHE_LOCATION_MASK) == DCACHE_LOCATION) { DoScratchpadAccess(phys_addr, value); - return 1; + return 0; } return m_bus->DispatchAccess(phys_addr, value); @@ -72,7 +72,7 @@ TickCount Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value) else WriteCacheControl(value); - return 1; + return 0; } else { diff --git a/src/core/cpu_recompiler_thunks.cpp b/src/core/cpu_recompiler_thunks.cpp index f51a4e3d3..aba55b280 100644 --- a/src/core/cpu_recompiler_thunks.cpp +++ b/src/core/cpu_recompiler_thunks.cpp @@ -14,7 +14,7 @@ u64 Thunks::ReadMemoryByte(Core* cpu, u32 address) return UINT64_C(0xFFFFFFFFFFFFFFFF); } - cpu->AddTicks(cycles - 1); + cpu->AddTicks(cycles); return ZeroExtend64(temp); } @@ -31,7 +31,7 @@ u64 Thunks::ReadMemoryHalfWord(Core* cpu, u32 address) return UINT64_C(0xFFFFFFFFFFFFFFFF); } - cpu->AddTicks(cycles - 1); + cpu->AddTicks(cycles); return ZeroExtend64(temp); } @@ -48,7 +48,7 @@ u64 Thunks::ReadMemoryWord(Core* cpu, u32 address) return UINT64_C(0xFFFFFFFFFFFFFFFF); } - cpu->AddTicks(cycles - 1); + cpu->AddTicks(cycles); return ZeroExtend64(temp); }