From 9359d0778e2776db00e00d608fc14062361b8892 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Wed, 25 Sep 2019 00:36:24 +1000 Subject: [PATCH] Clean up memory access handlers, reduce template specializations --- src/pse/bus.cpp | 85 ++++++++++++++++++++++------- src/pse/bus.h | 122 +++++++++++++++++++++++++++-------------- src/pse/bus.inl | 126 ++++++++++++++++++++----------------------- src/pse/cpu_core.cpp | 61 ++++++++++++++------- src/pse/cpu_core.h | 3 +- src/pse/cpu_core.inl | 10 ++-- src/pse/dma.cpp | 18 +++---- 7 files changed, 260 insertions(+), 165 deletions(-) diff --git a/src/pse/bus.cpp b/src/pse/bus.cpp index 97b140649..f8d3947d5 100644 --- a/src/pse/bus.cpp +++ b/src/pse/bus.cpp @@ -47,53 +47,65 @@ bool Bus::Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_co void Bus::Reset() { m_ram.fill(static_cast(0)); + m_MEMCTRL.exp1_base = 0x1F000000; + m_MEMCTRL.exp2_base = 0x1F802000; + m_MEMCTRL.exp1_delay_size = 0x0013243F; + m_MEMCTRL.exp3_delay_size = 0x00003022; + m_MEMCTRL.bios_delay_size = 0x0013243F; + m_MEMCTRL.spu_delay_size = 0x200931E1; + m_MEMCTRL.cdrom_delay_size = 0x00020843; + m_MEMCTRL.exp2_delay_size = 0x00070777; + m_MEMCTRL.common_delay_size = 0x00031125; + m_ram_size_reg = UINT32_C(0x00000B88); } bool Bus::DoState(StateWrapper& sw) { sw.DoBytes(m_ram.data(), m_ram.size()); sw.DoBytes(m_bios.data(), m_bios.size()); + sw.DoArray(m_MEMCTRL.regs, countof(m_MEMCTRL.regs)); + sw.Do(&m_ram_size_reg); sw.Do(&m_tty_line_buffer); return !sw.HasError(); } -bool Bus::ReadByte(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u8* value) +bool Bus::ReadByte(PhysicalMemoryAddress address, u8* value) { u32 temp = 0; - const bool result = DispatchAccess(cpu_address, bus_address, temp); + const bool result = DispatchAccess(address, temp); *value = Truncate8(temp); return result; } -bool Bus::ReadHalfWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u16* value) +bool Bus::ReadHalfWord(PhysicalMemoryAddress address, u16* value) { u32 temp = 0; const bool result = - DispatchAccess(cpu_address, bus_address, temp); + DispatchAccess(address, temp); *value = Truncate16(temp); return result; } -bool Bus::ReadWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32* value) +bool Bus::ReadWord(PhysicalMemoryAddress address, u32* value) { - return DispatchAccess(cpu_address, bus_address, *value); + return DispatchAccess(address, *value); } -bool Bus::WriteByte(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u8 value) +bool Bus::WriteByte(PhysicalMemoryAddress address, u8 value) { u32 temp = ZeroExtend32(value); - return DispatchAccess(cpu_address, bus_address, temp); + return DispatchAccess(address, temp); } -bool Bus::WriteHalfWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u16 value) +bool Bus::WriteHalfWord(PhysicalMemoryAddress address, u16 value) { u32 temp = ZeroExtend32(value); - return DispatchAccess(cpu_address, bus_address, temp); + return DispatchAccess(address, temp); } -bool Bus::WriteWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32 value) +bool Bus::WriteWord(PhysicalMemoryAddress address, u32 value) { - return DispatchAccess(cpu_address, bus_address, value); + return DispatchAccess(address, value); } void Bus::PatchBIOS(u32 address, u32 value, u32 mask /*= UINT32_C(0xFFFFFFFF)*/) @@ -154,8 +166,7 @@ bool Bus::LoadBIOS() return true; } -bool Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress cpu_address, - PhysicalMemoryAddress bus_address, u32& value) +bool Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress address, u32& value) { SmallString str; str.AppendString("Invalid bus "); @@ -171,7 +182,7 @@ bool Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, Physical else str.AppendString("write"); - str.AppendFormattedString(" at address 0x%08X (virtual address 0x%08X)", bus_address, cpu_address); + str.AppendFormattedString(" at address 0x%08X", address); if (type == MemoryAccessType::Write) str.AppendFormattedString(" (value 0x%08X)", value); @@ -185,7 +196,7 @@ bool Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, Physical bool Bus::DoReadEXP1(MemoryAccessSize size, u32 offset, u32& value) { if (m_exp1_rom.empty()) - return DoInvalidAccess(MemoryAccessType::Read, size, EXP1_BASE | offset, EXP1_BASE | offset, value); + return DoInvalidAccess(MemoryAccessType::Read, size, EXP1_BASE | offset, value); if (offset == 0x20018) { @@ -221,7 +232,7 @@ bool Bus::DoReadEXP1(MemoryAccessSize size, u32 offset, u32& value) bool Bus::DoWriteEXP1(MemoryAccessSize size, u32 offset, u32 value) { - return DoInvalidAccess(MemoryAccessType::Write, size, EXP1_BASE | offset, EXP1_BASE | offset, value); + return DoInvalidAccess(MemoryAccessType::Write, size, EXP1_BASE | offset, value); } bool Bus::DoReadEXP2(MemoryAccessSize size, u32 offset, u32& value) @@ -235,7 +246,7 @@ bool Bus::DoReadEXP2(MemoryAccessSize size, u32 offset, u32& value) return true; } - return DoInvalidAccess(MemoryAccessType::Read, size, EXP2_BASE | offset, EXP2_BASE | offset, value); + return DoInvalidAccess(MemoryAccessType::Read, size, EXP2_BASE | offset, value); } bool Bus::DoWriteEXP2(MemoryAccessSize size, u32 offset, u32 value) @@ -267,7 +278,43 @@ bool Bus::DoWriteEXP2(MemoryAccessSize size, u32 offset, u32 value) return true; } - return DoInvalidAccess(MemoryAccessType::Write, size, EXP2_BASE | offset, EXP2_BASE | offset, value); + return DoInvalidAccess(MemoryAccessType::Write, size, EXP2_BASE | offset, value); +} + +bool Bus::DoReadMemoryControl(MemoryAccessSize size, u32 offset, u32& value) +{ + FixupUnalignedWordAccessW32(offset, value); + value = m_MEMCTRL.regs[offset / 4]; + return true; +} + +bool Bus::DoWriteMemoryControl(MemoryAccessSize size, u32 offset, u32 value) +{ + FixupUnalignedWordAccessW32(offset, value); + m_MEMCTRL.regs[offset / 4] = value; + return true; +} + +bool Bus::DoReadMemoryControl2(MemoryAccessSize size, u32 offset, u32& value) +{ + if (offset == 0x00) + { + value = m_ram_size_reg; + return true; + } + + return DoInvalidAccess(MemoryAccessType::Read, size, MEMCTRL2_BASE | offset, value); +} + +bool Bus::DoWriteMemoryControl2(MemoryAccessSize size, u32 offset, u32 value) +{ + if (offset == 0x00) + { + m_ram_size_reg = value; + return true; + } + + return DoInvalidAccess(MemoryAccessType::Write, size, MEMCTRL2_BASE | offset, value); } bool Bus::DoReadPad(MemoryAccessSize size, u32 offset, u32& value) diff --git a/src/pse/bus.h b/src/pse/bus.h index 9fed1a64c..1a9c3788f 100644 --- a/src/pse/bus.h +++ b/src/pse/bus.h @@ -30,52 +30,84 @@ public: void Reset(); bool DoState(StateWrapper& sw); - bool ReadByte(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u8* value); - bool ReadHalfWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u16* value); - bool ReadWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32* value); - bool WriteByte(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u8 value); - bool WriteHalfWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u16 value); - bool WriteWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32 value); + bool ReadByte(PhysicalMemoryAddress address, u8* value); + bool ReadHalfWord(PhysicalMemoryAddress address, u16* value); + bool ReadWord(PhysicalMemoryAddress address, u32* value); + bool WriteByte(PhysicalMemoryAddress address, u8 value); + bool WriteHalfWord(PhysicalMemoryAddress address, u16 value); + bool WriteWord(PhysicalMemoryAddress address, u32 value); template - bool DispatchAccess(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32& value); + bool DispatchAccess(PhysicalMemoryAddress address, u32& value); void PatchBIOS(u32 address, u32 value, u32 mask = UINT32_C(0xFFFFFFFF)); void SetExpansionROM(std::vector data); private: - static constexpr u32 EXP1_BASE = 0x1F000000; - static constexpr u32 EXP1_SIZE = 0x800000; - static constexpr u32 EXP1_MASK = EXP1_SIZE - 1; - static constexpr u32 PAD_BASE = 0x1F801040; - static constexpr u32 PAD_SIZE = 0x10; - static constexpr u32 PAD_MASK = PAD_SIZE - 1; - static constexpr u32 SIO_BASE = 0x1F801050; - static constexpr u32 SIO_SIZE = 0x10; - static constexpr u32 SIO_MASK = SIO_SIZE - 1; - static constexpr u32 INTERRUPT_CONTROLLER_BASE = 0x1F801070; - static constexpr u32 INTERRUPT_CONTROLLER_SIZE = 0x08; - static constexpr u32 INTERRUPT_CONTROLLER_MASK = INTERRUPT_CONTROLLER_SIZE - 1; - static constexpr u32 DMA_BASE = 0x1F801080; - static constexpr u32 DMA_SIZE = 0x80; - static constexpr u32 DMA_MASK = DMA_SIZE - 1; - static constexpr u32 TIMERS_BASE = 0x1F801100; - static constexpr u32 TIMERS_SIZE = 0x40; - static constexpr u32 TIMERS_MASK = TIMERS_SIZE - 1; - static constexpr u32 CDROM_BASE = 0x1F801800; - static constexpr u32 CDROM_SIZE = 0x04; - static constexpr u32 CDROM_MASK = CDROM_SIZE - 1; - static constexpr u32 GPU_BASE = 0x1F801810; - static constexpr u32 GPU_SIZE = 0x10; - static constexpr u32 GPU_MASK = GPU_SIZE - 1; - static constexpr u32 SPU_BASE = 0x1F801C00; - static constexpr u32 SPU_SIZE = 0x300; - static constexpr u32 SPU_MASK = 0x3FF; - static constexpr u32 EXP2_BASE = 0x1F802000; - static constexpr u32 EXP2_SIZE = 0x2000; - static constexpr u32 EXP2_MASK = EXP2_SIZE - 1; - static constexpr u32 BIOS_BASE = 0x1FC00000; - static constexpr u32 BIOS_SIZE = 0x80000; + enum : u32 + { + EXP1_BASE = 0x1F000000, + EXP1_SIZE = 0x800000, + EXP1_MASK = EXP1_SIZE - 1, + MEMCTRL_BASE = 0x1F801000, + MEMCTRL_SIZE = 0x40, + MEMCTRL_MASK = MEMCTRL_SIZE - 1, + PAD_BASE = 0x1F801040, + PAD_SIZE = 0x10, + PAD_MASK = PAD_SIZE - 1, + SIO_BASE = 0x1F801050, + SIO_SIZE = 0x10, + SIO_MASK = SIO_SIZE - 1, + MEMCTRL2_BASE = 0x1F801060, + MEMCTRL2_SIZE = 0x10, + MEMCTRL2_MASK = MEMCTRL_SIZE - 1, + INTERRUPT_CONTROLLER_BASE = 0x1F801070, + INTERRUPT_CONTROLLER_SIZE = 0x10, + INTERRUPT_CONTROLLER_MASK = INTERRUPT_CONTROLLER_SIZE - 1, + DMA_BASE = 0x1F801080, + DMA_SIZE = 0x80, + DMA_MASK = DMA_SIZE - 1, + TIMERS_BASE = 0x1F801100, + TIMERS_SIZE = 0x40, + TIMERS_MASK = TIMERS_SIZE - 1, + CDROM_BASE = 0x1F801800, + CDROM_SIZE = 0x04, + CDROM_MASK = CDROM_SIZE - 1, + GPU_BASE = 0x1F801810, + GPU_SIZE = 0x10, + GPU_MASK = GPU_SIZE - 1, + SPU_BASE = 0x1F801C00, + SPU_SIZE = 0x300, + SPU_MASK = 0x3FF, + EXP2_BASE = 0x1F802000, + EXP2_SIZE = 0x2000, + EXP2_MASK = EXP2_SIZE - 1, + BIOS_BASE = 0x1FC00000, + BIOS_SIZE = 0x80000 + }; + + enum : u32 + { + MEMCTRL_REG_COUNT = 9 + }; + + union MEMCTRL + { + u32 regs[MEMCTRL_REG_COUNT]; + + struct + { + u32 exp1_base; + u32 exp2_base; + u32 exp1_delay_size; + u32 exp3_delay_size; + u32 bios_delay_size; + u32 spu_delay_size; + u32 cdrom_delay_size; + u32 exp2_delay_size; + u32 common_delay_size; + }; + }; bool LoadBIOS(); @@ -85,8 +117,7 @@ private: template bool DoBIOSAccess(u32 offset, u32& value); - bool DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress cpu_address, - PhysicalMemoryAddress bus_address, u32& value); + bool DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress address, u32& value); bool DoReadEXP1(MemoryAccessSize size, u32 offset, u32& value); bool DoWriteEXP1(MemoryAccessSize size, u32 offset, u32 value); @@ -94,6 +125,12 @@ private: bool DoReadEXP2(MemoryAccessSize size, u32 offset, u32& value); bool DoWriteEXP2(MemoryAccessSize size, u32 offset, u32 value); + bool DoReadMemoryControl(MemoryAccessSize size, u32 offset, u32& value); + bool DoWriteMemoryControl(MemoryAccessSize size, u32 offset, u32 value); + + bool DoReadMemoryControl2(MemoryAccessSize size, u32 offset, u32& value); + bool DoWriteMemoryControl2(MemoryAccessSize size, u32 offset, u32 value); + bool DoReadPad(MemoryAccessSize size, u32 offset, u32& value); bool DoWritePad(MemoryAccessSize size, u32 offset, u32 value); @@ -131,6 +168,9 @@ private: std::array m_bios{}; // 512K BIOS ROM std::vector m_exp1_rom; + MEMCTRL m_MEMCTRL = {}; + u32 m_ram_size_reg = 0; + String m_tty_line_buffer; }; diff --git a/src/pse/bus.inl b/src/pse/bus.inl index 885bd92f8..f9b41767f 100644 --- a/src/pse/bus.inl +++ b/src/pse/bus.inl @@ -74,117 +74,107 @@ bool Bus::DoBIOSAccess(u32 offset, u32& value) } template -bool Bus::DispatchAccess(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32& value) +bool Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value) { - if (bus_address < 0x800000) + if (address < 0x800000) { - return DoRAMAccess(bus_address, value); + return DoRAMAccess(address, value); } - else if (bus_address < EXP1_BASE) + else if (address < EXP1_BASE) { - return DoInvalidAccess(type, size, cpu_address, bus_address, value); + return DoInvalidAccess(type, size, address, value); } - else if (bus_address < (EXP1_BASE + EXP1_SIZE)) + else if (address < (EXP1_BASE + EXP1_SIZE)) { - return (type == MemoryAccessType::Read) ? DoReadEXP1(size, bus_address & EXP1_MASK, value) : - DoWriteEXP1(size, bus_address & EXP1_MASK, value); + return (type == MemoryAccessType::Read) ? DoReadEXP1(size, address & EXP1_MASK, value) : + DoWriteEXP1(size, address & EXP1_MASK, value); } - else if (bus_address < PAD_BASE) + else if (address < MEMCTRL_BASE) { - return DoInvalidAccess(type, size, cpu_address, bus_address, value); + return DoInvalidAccess(type, size, address, value); } - else if (bus_address < (PAD_BASE + PAD_SIZE)) + else if (address < (MEMCTRL_BASE + MEMCTRL_SIZE)) { - return (type == MemoryAccessType::Read) ? DoReadPad(size, bus_address & PAD_MASK, value) : - DoWritePad(size, bus_address & PAD_MASK, value); + return (type == MemoryAccessType::Read) ? DoReadMemoryControl(size, address & PAD_MASK, value) : + DoWriteMemoryControl(size, address & PAD_MASK, value); } - else if (bus_address < (SIO_BASE + SIO_SIZE)) + else if (address < (PAD_BASE + PAD_SIZE)) { - return (type == MemoryAccessType::Read) ? DoReadSIO(size, bus_address & SIO_MASK, value) : - DoWriteSIO(size, bus_address & SIO_MASK, value); + return (type == MemoryAccessType::Read) ? DoReadPad(size, address & PAD_MASK, value) : + DoWritePad(size, address & PAD_MASK, value); } - else if (bus_address < INTERRUPT_CONTROLLER_BASE) + else if (address < (SIO_BASE + SIO_SIZE)) { - return DoInvalidAccess(type, size, cpu_address, bus_address, value); + return (type == MemoryAccessType::Read) ? DoReadSIO(size, address & SIO_MASK, value) : + DoWriteSIO(size, address & SIO_MASK, value); } - else if (bus_address < (INTERRUPT_CONTROLLER_BASE + INTERRUPT_CONTROLLER_SIZE)) + else if (address < (MEMCTRL2_BASE + MEMCTRL2_SIZE)) + { + return (type == MemoryAccessType::Read) ? DoReadMemoryControl2(size, address & PAD_MASK, value) : + DoWriteMemoryControl2(size, address & PAD_MASK, value); + } + else if (address < (INTERRUPT_CONTROLLER_BASE + INTERRUPT_CONTROLLER_SIZE)) { return (type == MemoryAccessType::Read) ? - DoReadInterruptController(size, bus_address & INTERRUPT_CONTROLLER_MASK, value) : - DoWriteInterruptController(size, bus_address & INTERRUPT_CONTROLLER_MASK, value); + DoReadInterruptController(size, address & INTERRUPT_CONTROLLER_MASK, value) : + DoWriteInterruptController(size, address & INTERRUPT_CONTROLLER_MASK, value); } - else if (bus_address < DMA_BASE) + else if (address < (DMA_BASE + DMA_SIZE)) { - return DoInvalidAccess(type, size, cpu_address, bus_address, value); + return (type == MemoryAccessType::Read) ? DoReadDMA(size, address & DMA_MASK, value) : + DoWriteDMA(size, address & DMA_MASK, value); } - else if (bus_address < (DMA_BASE + DMA_SIZE)) + else if (address < (TIMERS_BASE + TIMERS_SIZE)) { - return (type == MemoryAccessType::Read) ? DoReadDMA(size, bus_address & DMA_MASK, value) : - DoWriteDMA(size, bus_address & DMA_MASK, value); + return (type == MemoryAccessType::Read) ? DoReadTimers(size, address & TIMERS_MASK, value) : + DoWriteTimers(size, address & TIMERS_MASK, value); } - else if (bus_address < TIMERS_BASE) + else if (address < CDROM_BASE) { - return DoInvalidAccess(type, size, cpu_address, bus_address, value); + return DoInvalidAccess(type, size, address, value); } - else if (bus_address < (TIMERS_BASE + TIMERS_SIZE)) + else if (address < (CDROM_BASE + GPU_SIZE)) { - return (type == MemoryAccessType::Read) ? DoReadTimers(size, bus_address & TIMERS_MASK, value) : - DoWriteTimers(size, bus_address & TIMERS_MASK, value); + return (type == MemoryAccessType::Read) ? DoReadCDROM(size, address & CDROM_MASK, value) : + DoWriteCDROM(size, address & CDROM_MASK, value); } - else if (bus_address < CDROM_BASE) + else if (address < GPU_BASE) { - return DoInvalidAccess(type, size, cpu_address, bus_address, value); + return DoInvalidAccess(type, size, address, value); } - else if (bus_address < (CDROM_BASE + GPU_SIZE)) + else if (address < (GPU_BASE + GPU_SIZE)) { - return (type == MemoryAccessType::Read) ? DoReadCDROM(size, bus_address & CDROM_MASK, value) : - DoWriteCDROM(size, bus_address & CDROM_MASK, value); + return (type == MemoryAccessType::Read) ? DoReadGPU(size, address & GPU_MASK, value) : + DoWriteGPU(size, address & GPU_MASK, value); } - else if (bus_address < GPU_BASE) + else if (address < SPU_BASE) { - return DoInvalidAccess(type, size, cpu_address, bus_address, value); + return DoInvalidAccess(type, size, address, value); } - else if (bus_address < (GPU_BASE + GPU_SIZE)) + else if (address < (SPU_BASE + SPU_SIZE)) { - return (type == MemoryAccessType::Read) ? DoReadGPU(size, bus_address & GPU_MASK, value) : - DoWriteGPU(size, bus_address & GPU_MASK, value); + return (type == MemoryAccessType::Read) ? DoReadSPU(size, address & SPU_MASK, value) : + DoWriteSPU(size, address & SPU_MASK, value); } - else if (bus_address < SPU_BASE) + else if (address < EXP2_BASE) { - return DoInvalidAccess(type, size, cpu_address, bus_address, value); + return DoInvalidAccess(type, size, address, value); } - else if (bus_address < (SPU_BASE + SPU_SIZE)) + else if (address < (EXP2_BASE + EXP2_SIZE)) { - return (type == MemoryAccessType::Read) ? DoReadSPU(size, bus_address & SPU_MASK, value) : - DoWriteSPU(size, bus_address & SPU_MASK, value); + return (type == MemoryAccessType::Read) ? DoReadEXP2(size, address & EXP2_MASK, value) : + DoWriteEXP2(size, address & EXP2_MASK, value); } - else if (bus_address < EXP2_BASE) + else if (address < BIOS_BASE) { - return DoInvalidAccess(type, size, cpu_address, bus_address, value); + return DoInvalidAccess(type, size, address, value); } - else if (bus_address < (EXP2_BASE + EXP2_SIZE)) + else if (address < (BIOS_BASE + BIOS_SIZE)) { - return (type == MemoryAccessType::Read) ? DoReadEXP2(size, bus_address & EXP2_MASK, value) : - DoWriteEXP2(size, bus_address & EXP2_MASK, value); - } - else if (bus_address < BIOS_BASE) - { - return DoInvalidAccess(type, size, cpu_address, bus_address, value); - } - else if (bus_address < (BIOS_BASE + BIOS_SIZE)) - { - return DoBIOSAccess(static_cast(bus_address - BIOS_BASE), value); - } - else if (bus_address < 0x1FFE0000) - { - return DoInvalidAccess(type, size, cpu_address, bus_address, value); - } - else if (bus_address < 0x1FFE0200) // I/O Ports (Cache Control) - { - return DoInvalidAccess(type, size, cpu_address, bus_address, value); + return DoBIOSAccess(static_cast(address - BIOS_BASE), value); } else { - return DoInvalidAccess(type, size, cpu_address, bus_address, value); + return DoInvalidAccess(type, size, address, value); } } diff --git a/src/pse/cpu_core.cpp b/src/pse/cpu_core.cpp index c8f1a61c7..3fcc49a72 100644 --- a/src/pse/cpu_core.cpp +++ b/src/pse/cpu_core.cpp @@ -92,8 +92,11 @@ void Core::SetPC(u32 new_pc) bool Core::ReadMemoryByte(VirtualMemoryAddress addr, u8* value) { u32 temp = 0; - const bool result = DoMemoryAccess(addr, temp); + const bool result = DoMemoryAccess(addr, temp); *value = Truncate8(temp); + if (!result) + RaiseException(Exception::DBE); + return result; } @@ -103,8 +106,11 @@ bool Core::ReadMemoryHalfWord(VirtualMemoryAddress addr, u16* value) return false; u32 temp = 0; - const bool result = DoMemoryAccess(addr, temp); + const bool result = DoMemoryAccess(addr, temp); *value = Truncate16(temp); + if (!result) + RaiseException(Exception::DBE); + return result; } @@ -113,13 +119,21 @@ bool Core::ReadMemoryWord(VirtualMemoryAddress addr, u32* value) if (!DoAlignmentCheck(addr)) return false; - return DoMemoryAccess(addr, *value); + const bool result = DoMemoryAccess(addr, *value); + if (!result) + RaiseException(Exception::DBE); + + return result; } bool Core::WriteMemoryByte(VirtualMemoryAddress addr, u8 value) { u32 temp = ZeroExtend32(value); - return DoMemoryAccess(addr, temp); + const bool result = DoMemoryAccess(addr, temp); + if (!result) + RaiseException(Exception::DBE); + + return result; } bool Core::WriteMemoryHalfWord(VirtualMemoryAddress addr, u16 value) @@ -128,7 +142,11 @@ bool Core::WriteMemoryHalfWord(VirtualMemoryAddress addr, u16 value) return false; u32 temp = ZeroExtend32(value); - return DoMemoryAccess(addr, temp); + const bool result = DoMemoryAccess(addr, temp); + if (!result) + RaiseException(Exception::DBE); + + return result; } bool Core::WriteMemoryWord(VirtualMemoryAddress addr, u32 value) @@ -136,13 +154,17 @@ bool Core::WriteMemoryWord(VirtualMemoryAddress addr, u32 value) if (!DoAlignmentCheck(addr)) return false; - return DoMemoryAccess(addr, value); + const bool result = DoMemoryAccess(addr, value); + if (!result) + RaiseException(Exception::DBE); + + return result; } bool Core::SafeReadMemoryByte(VirtualMemoryAddress addr, u8* value) { u32 temp = 0; - const bool result = DoMemoryAccess(addr, temp); + const bool result = DoMemoryAccess(addr, temp); *value = Truncate8(temp); return result; } @@ -150,31 +172,31 @@ bool Core::SafeReadMemoryByte(VirtualMemoryAddress addr, u8* value) bool Core::SafeReadMemoryHalfWord(VirtualMemoryAddress addr, u16* value) { u32 temp = 0; - const bool result = DoMemoryAccess(addr, temp); + const bool result = DoMemoryAccess(addr, temp); *value = Truncate16(temp); return result; } bool Core::SafeReadMemoryWord(VirtualMemoryAddress addr, u32* value) { - return DoMemoryAccess(addr, *value); + return DoMemoryAccess(addr, *value); } bool Core::SafeWriteMemoryByte(VirtualMemoryAddress addr, u8 value) { u32 temp = ZeroExtend32(value); - return DoMemoryAccess(addr, temp); + return DoMemoryAccess(addr, temp); } bool Core::SafeWriteMemoryHalfWord(VirtualMemoryAddress addr, u16 value) { u32 temp = ZeroExtend32(value); - return DoMemoryAccess(addr, temp); + return DoMemoryAccess(addr, temp); } bool Core::SafeWriteMemoryWord(VirtualMemoryAddress addr, u32 value) { - return DoMemoryAccess(addr, value); + return DoMemoryAccess(addr, value); } void Core::Branch(u32 target) @@ -420,8 +442,8 @@ static constexpr bool SubOverflow(u32 old_value, u32 sub_value, u32 new_value) void Core::DisassembleAndPrint(u32 addr) { - u32 bits; - DoMemoryAccess(addr, bits); + u32 bits = 0; + DoMemoryAccess(addr, bits); PrintInstruction(bits, addr); } @@ -459,14 +481,17 @@ bool Core::FetchInstruction() { m_regs.pc = m_regs.npc; - if (!DoAlignmentCheck( - static_cast(m_regs.npc)) || - !DoMemoryAccess( - static_cast(m_regs.npc), m_next_instruction.bits)) + if (!DoAlignmentCheck(static_cast(m_regs.npc))) { // this will call FetchInstruction() again when the pipeline is flushed. return false; } + if (!DoMemoryAccess(static_cast(m_regs.npc), + m_next_instruction.bits)) + { + RaiseException(Exception::IBE); + return false; + } m_regs.npc += sizeof(m_next_instruction.bits); return true; diff --git a/src/pse/cpu_core.h b/src/pse/cpu_core.h index 6c24d2376..4848572bc 100644 --- a/src/pse/cpu_core.h +++ b/src/pse/cpu_core.h @@ -41,6 +41,7 @@ public: // Sets the PC and flushes the pipeline. void SetPC(u32 new_pc); + // Memory reads variants which do not raise exceptions. bool SafeReadMemoryByte(VirtualMemoryAddress addr, u8* value); bool SafeReadMemoryHalfWord(VirtualMemoryAddress addr, u16* value); bool SafeReadMemoryWord(VirtualMemoryAddress addr, u32* value); @@ -53,7 +54,7 @@ public: void ClearExternalInterrupt(u8 bit); private: - template + template bool DoMemoryAccess(VirtualMemoryAddress address, u32& value); template diff --git a/src/pse/cpu_core.inl b/src/pse/cpu_core.inl index 386b93f8a..a22d5dc53 100644 --- a/src/pse/cpu_core.inl +++ b/src/pse/cpu_core.inl @@ -5,7 +5,7 @@ namespace CPU { -template +template bool Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value) { switch (address >> 29) @@ -25,7 +25,7 @@ bool Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value) return true; } - if (!m_bus->DispatchAccess(address, phys_addr, value)) + if (!m_bus->DispatchAccess(phys_addr, value)) { Panic("Bus error"); return false; @@ -39,7 +39,6 @@ bool Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value) case 0x03: // KUSEG 1536M-2048M { // Above 512mb raises an exception. - RaiseException(is_instruction_fetch ? Exception::IBE : Exception::DBE); return false; } @@ -58,7 +57,7 @@ bool Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value) return true; } - if (!m_bus->DispatchAccess(address, address & UINT32_C(0x1FFFFFFF), value)) + if (!m_bus->DispatchAccess(phys_addr, value)) { Panic("Bus error"); return false; @@ -71,7 +70,7 @@ bool Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value) case 0x05: // KSEG1 - physical memory uncached { const PhysicalMemoryAddress phys_addr = address & UINT32_C(0x1FFFFFFF); - if (!m_bus->DispatchAccess(address, phys_addr, value)) + if (!m_bus->DispatchAccess(phys_addr, value)) { Panic("Bus error"); return false; @@ -95,7 +94,6 @@ bool Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value) } else { - RaiseException(is_instruction_fetch ? Exception::IBE : Exception::DBE); return false; } } diff --git a/src/pse/dma.cpp b/src/pse/dma.cpp index a9ad5a302..5005a12c3 100644 --- a/src/pse/dma.cpp +++ b/src/pse/dma.cpp @@ -234,8 +234,7 @@ void DMA::RunDMA(Channel channel) words_remaining--; u32 value = 0; - m_bus->DispatchAccess(current_address, current_address, - value); + m_bus->DispatchAccess(current_address, value); DMAWrite(channel, value, current_address, words_remaining); current_address = (current_address + increment) & ADDRESS_MASK; @@ -249,8 +248,7 @@ void DMA::RunDMA(Channel channel) words_remaining--; u32 value = DMARead(channel, current_address, words_remaining); - m_bus->DispatchAccess(current_address, current_address, - value); + m_bus->DispatchAccess(current_address, value); current_address = (current_address + increment) & ADDRESS_MASK; } while (words_remaining > 0); @@ -269,8 +267,7 @@ void DMA::RunDMA(Channel channel) for (;;) { u32 header; - m_bus->DispatchAccess(current_address, current_address, - header); + m_bus->DispatchAccess(current_address, header); const u32 word_count = header >> 24; const u32 next_address = header & UINT32_C(0xFFFFFF); @@ -286,8 +283,7 @@ void DMA::RunDMA(Channel channel) words_remaining--; u32 memory_value = 0; - m_bus->DispatchAccess(current_address, current_address, - memory_value); + m_bus->DispatchAccess(current_address, memory_value); DMAWrite(channel, memory_value, current_address, words_remaining); current_address = (current_address + UINT32_C(4)) & ADDRESS_MASK; } while (words_remaining > 0); @@ -316,8 +312,7 @@ void DMA::RunDMA(Channel channel) words_remaining--; u32 value = 0; - m_bus->DispatchAccess(current_address, current_address, - value); + m_bus->DispatchAccess(current_address, value); DMAWrite(channel, value, current_address, words_remaining); current_address = (current_address + increment) & ADDRESS_MASK; @@ -331,8 +326,7 @@ void DMA::RunDMA(Channel channel) words_remaining--; u32 value = DMARead(channel, current_address, words_remaining); - m_bus->DispatchAccess(current_address, current_address, - value); + m_bus->DispatchAccess(current_address, value); current_address = (current_address + increment) & ADDRESS_MASK; } while (words_remaining > 0);